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

Reply via email to