mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 16:21:20 +03:00
Fix autovacuum work item error handling
In autovacuum's "work item" processing, a few strings were allocated in the current transaction's memory context, which goes away during error handling; if an error happened during execution of the work item, the pfree() calls to clean up afterwards would try to release already-released memory, possibly leading to a crash. In branch master, this was already fixed by commit 335f3d04e4c8, so backpatch that to REL_10_STABLE to fix the problem there too. As a secondary problem, verify that the autovacuum worker is connected to the right database for each work item; otherwise some items would be discarded by workers in other databases. Reported-by: Justin Pryzby Discussion: https://postgr.es/m/20171014035732.GB31726@telsasoft.com
This commit is contained in:
parent
0f1fbe7122
commit
52ca7572c3
@ -2444,8 +2444,10 @@ do_autovacuum(void)
|
|||||||
*/
|
*/
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
{
|
{
|
||||||
|
/* Use PortalContext for any per-table allocations */
|
||||||
|
MemoryContextSwitchTo(PortalContext);
|
||||||
|
|
||||||
/* have at it */
|
/* have at it */
|
||||||
MemoryContextSwitchTo(TopTransactionContext);
|
|
||||||
autovacuum_do_vac_analyze(tab, bstrategy);
|
autovacuum_do_vac_analyze(tab, bstrategy);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2482,6 +2484,9 @@ do_autovacuum(void)
|
|||||||
}
|
}
|
||||||
PG_END_TRY();
|
PG_END_TRY();
|
||||||
|
|
||||||
|
/* Make sure we're back in AutovacMemCxt */
|
||||||
|
MemoryContextSwitchTo(AutovacMemCxt);
|
||||||
|
|
||||||
did_vacuum = true;
|
did_vacuum = true;
|
||||||
|
|
||||||
/* the PGXACT flags are reset at the next end of transaction */
|
/* the PGXACT flags are reset at the next end of transaction */
|
||||||
@ -2525,6 +2530,8 @@ deleted:
|
|||||||
continue;
|
continue;
|
||||||
if (workitem->avw_active)
|
if (workitem->avw_active)
|
||||||
continue;
|
continue;
|
||||||
|
if (workitem->avw_database != MyDatabaseId)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* claim this one, and release lock while performing it */
|
/* claim this one, and release lock while performing it */
|
||||||
workitem->avw_active = true;
|
workitem->avw_active = true;
|
||||||
@ -2533,8 +2540,7 @@ deleted:
|
|||||||
perform_work_item(workitem);
|
perform_work_item(workitem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for config changes before acquiring lock for further
|
* Check for config changes before acquiring lock for further jobs.
|
||||||
* jobs.
|
|
||||||
*/
|
*/
|
||||||
CHECK_FOR_INTERRUPTS();
|
CHECK_FOR_INTERRUPTS();
|
||||||
if (got_SIGHUP)
|
if (got_SIGHUP)
|
||||||
@ -2601,10 +2607,9 @@ perform_work_item(AutoVacuumWorkItem *workitem)
|
|||||||
/*
|
/*
|
||||||
* Save the relation name for a possible error message, to avoid a catalog
|
* Save the relation name for a possible error message, to avoid a catalog
|
||||||
* lookup in case of an error. If any of these return NULL, then the
|
* lookup in case of an error. If any of these return NULL, then the
|
||||||
* relation has been dropped since last we checked; skip it. Note: they
|
* relation has been dropped since last we checked; skip it.
|
||||||
* 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_relname = get_rel_name(workitem->avw_relation);
|
||||||
cur_nspname = get_namespace_name(get_rel_namespace(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);
|
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
|
* We will abort the current work item if something errors out, and
|
||||||
* continue with the next one; in particular, this happens if we are
|
* continue with the next one; in particular, this happens if we are
|
||||||
@ -2622,9 +2630,10 @@ perform_work_item(AutoVacuumWorkItem *workitem)
|
|||||||
*/
|
*/
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
{
|
{
|
||||||
/* have at it */
|
/* Use PortalContext for any per-work-item allocations */
|
||||||
MemoryContextSwitchTo(TopTransactionContext);
|
MemoryContextSwitchTo(PortalContext);
|
||||||
|
|
||||||
|
/* have at it */
|
||||||
switch (workitem->avw_type)
|
switch (workitem->avw_type)
|
||||||
{
|
{
|
||||||
case AVW_BRINSummarizeRange:
|
case AVW_BRINSummarizeRange:
|
||||||
@ -2668,6 +2677,9 @@ perform_work_item(AutoVacuumWorkItem *workitem)
|
|||||||
}
|
}
|
||||||
PG_END_TRY();
|
PG_END_TRY();
|
||||||
|
|
||||||
|
/* Make sure we're back in AutovacMemCxt */
|
||||||
|
MemoryContextSwitchTo(AutovacMemCxt);
|
||||||
|
|
||||||
/* We intentionally do not set did_vacuum here */
|
/* We intentionally do not set did_vacuum here */
|
||||||
|
|
||||||
/* be tidy */
|
/* be tidy */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user