Foreign data wrapper's IterateForeignScan() function is supposed to be
called in a short-lived memory context, but the memory context is
actually not reset during query execution. That's a pretty bad memory
leak. I've been testing this with file_fdw and a large file, and "SELECT
COUNT(*) FROM foreign_table"
Interestingly, if you add any WHERE clause to it, the memory context is
reset in ExecScan and the leak goes away. This is only a problem with
the fastpath in ExecScan for the case of no quals and no projections.
The trivial fix is to reset the per-tuple memory context between
iterations. I tried to look around for other executor nodes that might
have the same problem. I didn't see any obvious leaks, although index
scan node seems to call AM's getnext without resetting the memory
context in between. That's a pretty well-tested codepath, however, and
there hasn't been any complains of leaks with index scans, so there must
be something that mitigates it.
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index d50489c..2e36da0 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -44,7 +44,11 @@ ForeignNext(ForeignScanState *node)
ExprContext *econtext = node->ss.ps.ps_ExprContext;
MemoryContext oldcontext;
- /* Call the Iterate function in short-lived context */
+ /*
+ * Call the Iterate function in short-lived context. Reset it first
+ * to free any leftovers from previous iteration.
+ */
+ ResetExprContext(econtext);
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
slot = node->fdwroutine->IterateForeignScan(node);
MemoryContextSwitchTo(oldcontext);
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers