Improve memory management in autovacuum.c.

Invoke vacuum(), as well as "work item" processing, in the PortalContext
that do_autovacuum() has manufactured, which will be reset before each
such invocation.  This ensures cleanup of any memory leaked by these
operations.  It also avoids the rather dangerous practice of calling
vacuum() in a context that vacuum() itself will destroy while it runs.
There's no known live bug there, but it's not hard to imagine introducing
one if we leave it like this.

Tom Lane, reviewed by Michael Paquier and Alvaro Herrera

Discussion: https://postgr.es/m/13849.1506114543@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2017-09-23 13:28:16 -04:00
parent ad51c6fb57
commit 335f3d04e4
1 changed files with 17 additions and 5 deletions

View File

@ -2444,8 +2444,10 @@ do_autovacuum(void)
*/
PG_TRY();
{
/* Use PortalContext for any per-table allocations */
MemoryContextSwitchTo(PortalContext);
/* have at it */
MemoryContextSwitchTo(TopTransactionContext);
autovacuum_do_vac_analyze(tab, bstrategy);
/*
@ -2482,6 +2484,9 @@ do_autovacuum(void)
}
PG_END_TRY();
/* Make sure we're back in AutovacMemCxt */
MemoryContextSwitchTo(AutovacMemCxt);
did_vacuum = true;
/* the PGXACT flags are reset at the next end of transaction */
@ -2533,8 +2538,7 @@ deleted:
perform_work_item(workitem);
/*
* Check for config changes before acquiring lock for further
* jobs.
* Check for config changes before acquiring lock for further jobs.
*/
CHECK_FOR_INTERRUPTS();
if (got_SIGHUP)
@ -2605,6 +2609,7 @@ perform_work_item(AutoVacuumWorkItem *workitem)
* must live in a long-lived memory context because we call vacuum and
* analyze in different transactions.
*/
Assert(CurrentMemoryContext == AutovacMemCxt);
cur_relname = get_rel_name(workitem->avw_relation);
cur_nspname = get_namespace_name(get_rel_namespace(workitem->avw_relation));
@ -2614,6 +2619,9 @@ perform_work_item(AutoVacuumWorkItem *workitem)
autovac_report_workitem(workitem, cur_nspname, cur_datname);
/* clean up memory before each work item */
MemoryContextResetAndDeleteChildren(PortalContext);
/*
* We will abort the current work item if something errors out, and
* continue with the next one; in particular, this happens if we are
@ -2622,9 +2630,10 @@ perform_work_item(AutoVacuumWorkItem *workitem)
*/
PG_TRY();
{
/* have at it */
MemoryContextSwitchTo(TopTransactionContext);
/* Use PortalContext for any per-work-item allocations */
MemoryContextSwitchTo(PortalContext);
/* have at it */
switch (workitem->avw_type)
{
case AVW_BRINSummarizeRange:
@ -2668,6 +2677,9 @@ perform_work_item(AutoVacuumWorkItem *workitem)
}
PG_END_TRY();
/* Make sure we're back in AutovacMemCxt */
MemoryContextSwitchTo(AutovacMemCxt);
/* We intentionally do not set did_vacuum here */
/* be tidy */