Avoid crash in interrupted autovacuum worker, caused by leaving the current

memory context pointing at a context not long lived enough.

Also, create a fake PortalContext where to store the vac_context, if only
to avoid having it be a top-level memory context.
This commit is contained in:
Alvaro Herrera 2007-06-30 04:08:05 +00:00
parent 10af02b912
commit 2910ccefb4
1 changed files with 33 additions and 15 deletions

View File

@ -55,7 +55,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.52 2007/06/29 17:07:39 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.53 2007/06/30 04:08:05 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@ -1427,8 +1427,8 @@ AutoVacWorkerMain(int argc, char *argv[])
pqsignal(SIGHUP, SIG_IGN);
/*
* Presently, SIGINT will lead to autovacuum shutdown, because that's how
* we handle ereport(ERROR). It could be improved however.
* SIGINT is used to signal cancelling the current table's vacuum;
* SIGTERM means abort and exit cleanly, and SIGQUIT means abandon ship.
*/
pqsignal(SIGINT, StatementCancelHandler);
pqsignal(SIGTERM, die);
@ -1513,6 +1513,7 @@ AutoVacWorkerMain(int argc, char *argv[])
/* insert into the running list */
SHMQueueInsertBefore(&AutoVacuumShmem->av_runningWorkers,
&MyWorkerInfo->wi_links);
/*
* remove from the "starting" pointer, so that the launcher can start
* a new worker if required
@ -1560,13 +1561,6 @@ AutoVacWorkerMain(int argc, char *argv[])
ereport(DEBUG1,
(errmsg("autovacuum: processing database \"%s\"", dbname)));
/* Create the memory context where cross-transaction state is stored */
AutovacMemCxt = AllocSetContextCreate(TopMemoryContext,
"AV worker",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/* And do an appropriate amount of work */
recentXid = ReadNewTransactionId();
do_autovacuum();
@ -1787,6 +1781,18 @@ do_autovacuum(void)
PgStat_StatDBEntry *dbentry;
BufferAccessStrategy bstrategy;
/*
* StartTransactionCommand and CommitTransactionCommand will automatically
* switch to other contexts. We need this one to keep the list of
* relations to vacuum/analyze across transactions.
*/
AutovacMemCxt = AllocSetContextCreate(TopMemoryContext,
"AV worker",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
MemoryContextSwitchTo(AutovacMemCxt);
/*
* may be NULL if we couldn't find an entry (only happens if we
* are forcing a vacuum for anti-wrap purposes).
@ -1825,11 +1831,7 @@ do_autovacuum(void)
ReleaseSysCache(tuple);
/*
* StartTransactionCommand and CommitTransactionCommand will automatically
* switch to other contexts. We need this one to keep the list of
* relations to vacuum/analyze across transactions.
*/
/* StartTransactionCommand changed elsewhere */
MemoryContextSwitchTo(AutovacMemCxt);
/* The database hash where pgstat keeps shared relations */
@ -1932,6 +1934,16 @@ do_autovacuum(void)
*/
bstrategy = GetAccessStrategy(BAS_VACUUM);
/*
* create a memory context to act as fake PortalContext, so that the
* contexts created in the vacuum code are cleaned up for each table.
*/
PortalContext = AllocSetContextCreate(AutovacMemCxt,
"Autovacuum Portal",
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/*
* Perform operations on collected tables.
*/
@ -1996,6 +2008,7 @@ next_worker:
* FIXME we ignore the possibility that the table was finished being
* vacuumed in the last 500ms (PGSTAT_STAT_INTERVAL). This is a bug.
*/
MemoryContextSwitchTo(AutovacMemCxt);
tab = table_recheck_autovac(relid);
if (tab == NULL)
{
@ -2026,6 +2039,9 @@ next_worker:
autovac_balance_cost();
LWLockRelease(AutovacuumLock);
/* clean up memory before each iteration */
MemoryContextResetAndDeleteChildren(PortalContext);
/*
* We will abort vacuuming the current table if we are interrupted, and
* continue with the next one in schedule; but if anything else
@ -2035,6 +2051,7 @@ next_worker:
PG_TRY();
{
/* have at it */
MemoryContextSwitchTo(TopTransactionContext);
autovacuum_do_vac_analyze(tab->at_relid,
tab->at_dovacuum,
tab->at_doanalyze,
@ -2063,6 +2080,7 @@ next_worker:
AbortOutOfAnyTransaction();
FlushErrorState();
MemoryContextResetAndDeleteChildren(PortalContext);
/* restart our transaction for the following operations */
StartTransactionCommand();