Received: from malur.postgresql.org ([2a02:16a8:dc51::56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1foK8V-0004Sw-9u for pgsql-bugs@arkaria.postgresql.org; Sat, 11 Aug 2018 03:00:15 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1foK8T-0001tg-HB for pgsql-bugs@arkaria.postgresql.org; Sat, 11 Aug 2018 03:00:13 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1foK8T-0001tH-7k for pgsql-bugs@lists.postgresql.org; Sat, 11 Aug 2018 03:00:13 +0000 Received: from lungold.riddles.org.uk ([82.68.208.19]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1foK8Q-0001aX-0a for pgsql-bugs@lists.postgresql.org; Sat, 11 Aug 2018 03:00:12 +0000 Received: from [192.168.127.1] (port=37092 helo=caithnard.riddles.org.uk) by lungold.riddles.org.uk with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.88 (FreeBSD)) (envelope-from ) id 1foK8L-0000r8-Aw; Sat, 11 Aug 2018 03:00:05 +0000 Received: from [127.0.0.1] (port=63540 helo=caithnard.riddles.org.uk) by caithnard.riddles.org.uk with esmtp (Exim 4.89 (FreeBSD)) (envelope-from ) id 1foK8K-000PbV-LX; Sat, 11 Aug 2018 03:00:04 +0000 From: Andrew Gierth To: pgsql-bugs@lists.postgresql.org Cc: Alvaro Herrera , Pavel Stehule Subject: Re: BUG #15321: XMLTABLE leaks memory like crazy In-Reply-To: <87va8h7nyl.fsf@news-spur.riddles.org.uk> (Andrew Gierth's message of "Sat, 11 Aug 2018 01:28:47 +0100") Message-ID: <87r2j57hdo.fsf@news-spur.riddles.org.uk> References: <153394403528.10284.7530399040974170549@wrigleys.postgresql.org> <87va8h7nyl.fsf@news-spur.riddles.org.uk> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1 (berkeley-unix) Date: Sat, 11 Aug 2018 04:00:04 +0100 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --=-=-= Content-Type: text/plain >>>>> "Andrew" == Andrew Gierth writes: >>> * I removed the "buildercxt" memory context. It seemed mostly >>> pointless, and I was disturbed by the MemoryContextResetOnly(). >>> Per-value memory still uses the per-value memory context, but the >>> rest of the stuff is in the per-query context, which should be >>> pretty much the same. Andrew> A quick reading suggests that the per-value context should have Andrew> been changed to not be a child of "buildercxt" (which would Andrew> avoid the MemoryContextResetOnly issue - that's a good sign Andrew> that you've put a child context under the wrong parent). But Andrew> the use of the per-query context instead is exactly what causes Andrew> this blowup; compare with what nodeFunctionscan does with its Andrew> "argcontext" (and the corresponding comments in Andrew> ExecMakeTableFunctionResult). And here's a patch (against pg10, but I don't think the code's changed since) that I think does it the right way. This works by changing the meaning of perValueCxt - it's now the per-INPUT-value context (equivalent to FunctionScan's argcontext, but I didn't change the name for simplicity), not per-output-value; for the latter, we use the result exprcontext's per-tuple memory like everything else does (cf. FunctionScan). I've verified that this fixes the leak; it also passes all other tests I have thrown at it. Anyone see any issues with this? (CC'ing in Pavel as original author) I'll apply it in due course unless anyone says otherwise. -- Andrew (irc:RhodiumToad) --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=xmlmem.patch Content-Description: xmltable memory leak fix diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c index b03d2ef762..222711bb5a 100644 --- a/src/backend/executor/nodeTableFuncscan.c +++ b/src/backend/executor/nodeTableFuncscan.c @@ -288,6 +288,9 @@ tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext) oldcxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); tstate->tupstore = tuplestore_begin_heap(false, false, work_mem); + MemoryContextReset(tstate->perValueCxt); + MemoryContextSwitchTo(tstate->perValueCxt); + PG_TRY(); { routine->InitOpaque(tstate, @@ -319,8 +322,7 @@ tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext) } PG_END_TRY(); - /* return to original memory context, and clean up */ - MemoryContextSwitchTo(oldcxt); + /* clean up and return to original memory context */ if (tstate->opaque != NULL) { @@ -328,6 +330,9 @@ tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext) tstate->opaque = NULL; } + MemoryContextSwitchTo(oldcxt); + MemoryContextReset(tstate->perValueCxt); + return; } @@ -433,7 +438,7 @@ tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext) ordinalitycol = ((TableFuncScan *) (tstate->ss.ps.plan))->tablefunc->ordinalitycol; - oldcxt = MemoryContextSwitchTo(tstate->perValueCxt); + oldcxt = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); /* * Keep requesting rows from the table builder until there aren't any. @@ -496,7 +501,7 @@ tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext) tuplestore_putvalues(tstate->tupstore, tupdesc, values, nulls); - MemoryContextReset(tstate->perValueCxt); + MemoryContextReset(econtext->ecxt_per_tuple_memory); } MemoryContextSwitchTo(oldcxt); --=-=-=--