aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-08-26 15:04:05 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2016-08-26 15:04:10 -0400
commitbef2d627f30c0d854d02dc860b0d54fa3309d4ee (patch)
tree853464e5bf7070e31772bc85f63f069c0f98ea3b
parent42ebdc8129f038e06e17d7b3da7fc11897323814 (diff)
downloadpostgresql-bef2d627f30c0d854d02dc860b0d54fa3309d4ee.tar.gz
postgresql-bef2d627f30c0d854d02dc860b0d54fa3309d4ee.zip
Fix potential memory leakage from HandleParallelMessages().
HandleParallelMessages leaked memory into the caller's context. Since it's called from ProcessInterrupts, there is basically zero certainty as to what CurrentMemoryContext is, which means we could be leaking into long-lived contexts. Over the processing of many worker messages that would grow to be a problem. Things could be even worse than just a leak, if we happened to service the interrupt while ErrorContext is current: elog.c thinks it can reset that on its own whim, possibly yanking storage out from under HandleParallelMessages. Give HandleParallelMessages its own dedicated context instead, which we can reset during each call to ensure there's no accumulation of wasted memory. Discussion: <16610.1472222135@sss.pgh.pa.us>
-rw-r--r--src/backend/access/transam/parallel.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index ec6e1c5e6dc..949bfb8b3e6 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -702,6 +702,9 @@ void
HandleParallelMessages(void)
{
dlist_iter iter;
+ MemoryContext oldcontext;
+
+ static MemoryContext hpm_context = NULL;
/*
* This is invoked from ProcessInterrupts(), and since some of the
@@ -712,6 +715,23 @@ HandleParallelMessages(void)
*/
HOLD_INTERRUPTS();
+ /*
+ * Moreover, CurrentMemoryContext might be pointing almost anywhere. We
+ * don't want to risk leaking data into long-lived contexts, so let's do
+ * our work here in a private context that we can reset on each use.
+ */
+ if (hpm_context == NULL) /* first time through? */
+ hpm_context = AllocSetContextCreate(TopMemoryContext,
+ "HandleParallelMessages context",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
+ else
+ MemoryContextReset(hpm_context);
+
+ oldcontext = MemoryContextSwitchTo(hpm_context);
+
+ /* OK to process messages. Reset the flag saying there are more to do. */
ParallelMessagePending = false;
dlist_foreach(iter, &pcxt_list)
@@ -758,6 +778,11 @@ HandleParallelMessages(void)
}
}
+ MemoryContextSwitchTo(oldcontext);
+
+ /* Might as well clear the context on our way out */
+ MemoryContextReset(hpm_context);
+
RESUME_INTERRUPTS();
}