From a17d169442b13a5655c3d5f75941f30b7452e505 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Sat, 4 Nov 2017 23:44:02 +0100 Subject: [PATCH 6/6] remove-memory-leak-protection-v1 --- src/backend/executor/nodeGather.c | 14 ++------------ src/backend/executor/nodeGatherMerge.c | 10 +--------- src/backend/executor/tqueue.c | 2 ++ 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c index 856db9e0f1..30f4394b30 100644 --- a/src/backend/executor/nodeGather.c +++ b/src/backend/executor/nodeGather.c @@ -129,7 +129,6 @@ static TupleTableSlot * ExecGather(PlanState *pstate) { GatherState *node = castNode(GatherState, pstate); - TupleTableSlot *fslot = node->funnel_slot; TupleTableSlot *slot; ExprContext *econtext; @@ -201,11 +200,8 @@ ExecGather(PlanState *pstate) /* * Reset per-tuple memory context to free any expression evaluation - * storage allocated in the previous tuple cycle. This will also clear - * any previous tuple returned by a TupleQueueReader; to make sure we - * don't leave a dangling pointer around, clear the working slot first. + * storage allocated in the previous tuple cycle. */ - ExecClearTuple(fslot); econtext = node->ps.ps_ExprContext; ResetExprContext(econtext); @@ -254,7 +250,6 @@ gather_getnext(GatherState *gatherstate) PlanState *outerPlan = outerPlanState(gatherstate); TupleTableSlot *outerTupleSlot; TupleTableSlot *fslot = gatherstate->funnel_slot; - MemoryContext tupleContext = gatherstate->ps.ps_ExprContext->ecxt_per_tuple_memory; HeapTuple tup; while (gatherstate->nreaders > 0 || gatherstate->need_to_scan_locally) @@ -263,12 +258,7 @@ gather_getnext(GatherState *gatherstate) if (gatherstate->nreaders > 0) { - MemoryContext oldContext; - - /* Run TupleQueueReaders in per-tuple context */ - oldContext = MemoryContextSwitchTo(tupleContext); tup = gather_readnext(gatherstate); - MemoryContextSwitchTo(oldContext); if (HeapTupleIsValid(tup)) { @@ -276,7 +266,7 @@ gather_getnext(GatherState *gatherstate) fslot, /* slot in which to store the tuple */ InvalidBuffer, /* buffer associated with this * tuple */ - false); /* slot should not pfree tuple */ + true); /* pfree tuple when done with it */ return fslot; } } diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c index 6da607b7c4..1f9818233b 100644 --- a/src/backend/executor/nodeGatherMerge.c +++ b/src/backend/executor/nodeGatherMerge.c @@ -605,7 +605,7 @@ load_tuple_array(GatherMergeState *gm_state, int reader) &tuple_buffer->done); if (!HeapTupleIsValid(tuple)) break; - tuple_buffer->tuple[i] = heap_copytuple(tuple); + tuple_buffer->tuple[i] = tuple; tuple_buffer->nTuples++; } } @@ -669,7 +669,6 @@ gather_merge_readnext(GatherMergeState *gm_state, int reader, bool nowait) &tuple_buffer->done); if (!HeapTupleIsValid(tup)) return false; - tup = heap_copytuple(tup); /* * Attempt to read more tuples in nowait mode and store them in the @@ -699,20 +698,13 @@ gm_readnext_tuple(GatherMergeState *gm_state, int nreader, bool nowait, { TupleQueueReader *reader; HeapTuple tup; - MemoryContext oldContext; - MemoryContext tupleContext; /* Check for async events, particularly messages from workers. */ CHECK_FOR_INTERRUPTS(); /* Attempt to read a tuple. */ reader = gm_state->reader[nreader - 1]; - - /* Run TupleQueueReaders in per-tuple context */ - tupleContext = gm_state->ps.ps_ExprContext->ecxt_per_tuple_memory; - oldContext = MemoryContextSwitchTo(tupleContext); tup = TupleQueueReaderNext(reader, nowait, done); - MemoryContextSwitchTo(oldContext); return tup; } diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c index 4a295c936b..0dcb911c3c 100644 --- a/src/backend/executor/tqueue.c +++ b/src/backend/executor/tqueue.c @@ -161,6 +161,8 @@ DestroyTupleQueueReader(TupleQueueReader *reader) * is set to true when there are no remaining tuples and otherwise to false. * * The returned tuple, if any, is allocated in CurrentMemoryContext. + * Note that this routine must not leak memory! (We used to allow that, + * but not any more.) * * Even when shm_mq_receive() returns SHM_MQ_WOULD_BLOCK, this can still * accumulate bytes from a partially-read message, so it's useful to call -- 2.13.5 (Apple Git-94)