From 1dde5782e34a1c5ef2ce9d97cf18007fed5fde92 Mon Sep 17 00:00:00 2001
From: Joe Conway <mail@joeconway.com>
Date: Fri, 20 Jun 2014 12:22:13 -0700
Subject: [PATCH] Clean up data conversion short-lived memory context.

dblink uses a short-lived data conversion memory context. However it
was not deleted when no longer needed, leading to a noticeable memory
leak under some circumstances. Plug the hole, along with minor
refactoring. Backpatch to 9.2 where the leak was introduced.

Report and initial patch by MauMau. Reviewed/modified slightly by
Tom Lane and me.
---
 contrib/dblink/dblink.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index a81853fa911..d77b3ee34ba 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -977,6 +977,13 @@ materializeQueryResult(FunctionCallInfo fcinfo,
 
 	PG_TRY();
 	{
+		/* Create short-lived memory context for data conversions */
+		sinfo.tmpcontext = AllocSetContextCreate(CurrentMemoryContext,
+												 "dblink temporary context",
+												 ALLOCSET_DEFAULT_MINSIZE,
+												 ALLOCSET_DEFAULT_INITSIZE,
+												 ALLOCSET_DEFAULT_MAXSIZE);
+
 		/* execute query, collecting any tuples into the tuplestore */
 		res = storeQueryResult(&sinfo, conn, sql);
 
@@ -1041,6 +1048,12 @@ materializeQueryResult(FunctionCallInfo fcinfo,
 			PQclear(res);
 			res = NULL;
 		}
+
+		/* clean up data conversion short-lived memory context */
+		if (sinfo.tmpcontext != NULL)
+			MemoryContextDelete(sinfo.tmpcontext);
+		sinfo.tmpcontext = NULL;
+
 		PQclear(sinfo.last_res);
 		sinfo.last_res = NULL;
 		PQclear(sinfo.cur_res);
@@ -1204,15 +1217,6 @@ storeRow(storeInfo *sinfo, PGresult *res, bool first)
 		if (sinfo->cstrs)
 			pfree(sinfo->cstrs);
 		sinfo->cstrs = (char **) palloc(nfields * sizeof(char *));
-
-		/* Create short-lived memory context for data conversions */
-		if (!sinfo->tmpcontext)
-			sinfo->tmpcontext =
-				AllocSetContextCreate(CurrentMemoryContext,
-									  "dblink temporary context",
-									  ALLOCSET_DEFAULT_MINSIZE,
-									  ALLOCSET_DEFAULT_INITSIZE,
-									  ALLOCSET_DEFAULT_MAXSIZE);
 	}
 
 	/* Should have a single-row result if we get here */
-- 
GitLab