Move interrupt-handling code into subroutines.

Some auxiliary processes, as well as the autovacuum launcher,
have interrupt handling code directly in their main loops.
Try to abstract things a little better by moving it into
separate functions.

This doesn't make any functional difference, and leaves
in place relatively large differences among processes in how
interrupts are handled, but hopefully it at least makes it
easier to see the commonalities and differences across
process types.

Patch by me, reviewed by Andres Freund and Daniel Gustafsson.

Discussion: http://postgr.es/m/CA+TgmoZwDk=BguVDVa+qdA6SBKef=PKbaKDQALTC_9qoz1mJqg@mail.gmail.com
This commit is contained in:
Robert Haas 2019-12-17 12:55:13 -05:00
parent af3290f5e7
commit 5910d6c7e3
4 changed files with 133 additions and 86 deletions

View File

@ -311,6 +311,8 @@ NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_nore
NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn();
static Oid do_start_worker(void);
static void HandleAutoVacLauncherInterrupts(void);
static void AutoVacLauncherShutdown() pg_attribute_noreturn();
static void launcher_determine_sleep(bool canlaunch, bool recursing,
struct timeval *nap);
static void launch_worker(TimestampTz now);
@ -554,7 +556,7 @@ AutoVacLauncherMain(int argc, char *argv[])
/* if in shutdown mode, no need for anything further; just go away */
if (got_SIGTERM)
goto shutdown;
AutoVacLauncherShutdown();
/*
* Sleep at least 1 second after any error. We don't want to be
@ -649,30 +651,7 @@ AutoVacLauncherMain(int argc, char *argv[])
ResetLatch(MyLatch);
/* Process sinval catchup interrupts that happened while sleeping */
ProcessCatchupInterrupt();
/* the normal shutdown case */
if (got_SIGTERM)
break;
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
/* shutdown requested in config file? */
if (!AutoVacuumingActive())
break;
/* rebalance in case the default cost parameters changed */
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
autovac_balance_cost();
LWLockRelease(AutovacuumLock);
/* rebuild the list in case the naptime changed */
rebuild_database_list(InvalidOid);
}
HandleAutoVacLauncherInterrupts();
/*
* a worker finished, or postmaster signalled failure to start a
@ -813,8 +792,47 @@ AutoVacLauncherMain(int argc, char *argv[])
}
}
/* Normal exit from the autovac launcher is here */
shutdown:
AutoVacLauncherShutdown();
}
/*
* Process any new interrupts.
*/
static void
HandleAutoVacLauncherInterrupts(void)
{
/* the normal shutdown case */
if (got_SIGTERM)
AutoVacLauncherShutdown();
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
/* shutdown requested in config file? */
if (!AutoVacuumingActive())
AutoVacLauncherShutdown();
/* rebalance in case the default cost parameters changed */
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
autovac_balance_cost();
LWLockRelease(AutovacuumLock);
/* rebuild the list in case the naptime changed */
rebuild_database_list(InvalidOid);
}
/* Process sinval catchup interrupts that happened while sleeping */
ProcessCatchupInterrupt();
}
/*
* Perform a normal exit from the autovac launcher.
*/
static void
AutoVacLauncherShutdown()
{
ereport(DEBUG1,
(errmsg("autovacuum launcher shutting down")));
AutoVacuumShmem->av_launcherpid = 0;

View File

@ -92,6 +92,8 @@ static XLogRecPtr last_snapshot_lsn = InvalidXLogRecPtr;
static volatile sig_atomic_t got_SIGHUP = false;
static volatile sig_atomic_t shutdown_requested = false;
static void HandleBackgroundWriterInterrupts(void);
/* Signal handlers */
static void bg_quickdie(SIGNAL_ARGS);
@ -241,21 +243,7 @@ BackgroundWriterMain(void)
/* Clear any already-pending wakeups */
ResetLatch(MyLatch);
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
}
if (shutdown_requested)
{
/*
* From here on, elog(ERROR) should end with exit(1), not send
* control back to the sigsetjmp block above
*/
ExitOnAnyError = true;
/* Normal exit from the bgwriter is here */
proc_exit(0); /* done */
}
HandleBackgroundWriterInterrupts();
/*
* Do one cycle of dirty-buffer writing.
@ -369,6 +357,30 @@ BackgroundWriterMain(void)
}
}
/*
* Process any new interrupts.
*/
static void
HandleBackgroundWriterInterrupts(void)
{
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
}
if (shutdown_requested)
{
/*
* From here on, elog(ERROR) should end with exit(1), not send
* control back to the sigsetjmp block above
*/
ExitOnAnyError = true;
/* Normal exit from the bgwriter is here */
proc_exit(0); /* done */
}
}
/* --------------------------------
* signal handler routines

View File

@ -169,6 +169,7 @@ static pg_time_t last_xlog_switch_time;
/* Prototypes for private functions */
static void HandleCheckpointerInterrupts();
static void CheckArchiveTimeout(void);
static bool IsCheckpointOnSchedule(double progress);
static bool ImmediateCheckpointRequested(void);
@ -350,37 +351,7 @@ CheckpointerMain(void)
* Process any requests or signals received recently.
*/
AbsorbSyncRequests();
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
/*
* Checkpointer is the last process to shut down, so we ask it to
* hold the keys for a range of other tasks required most of which
* have nothing to do with checkpointing at all.
*
* For various reasons, some config values can change dynamically
* so the primary copy of them is held in shared memory to make
* sure all backends see the same value. We make Checkpointer
* responsible for updating the shared memory copy if the
* parameter setting changes because of SIGHUP.
*/
UpdateSharedMemoryConfig();
}
if (shutdown_requested)
{
/*
* From here on, elog(ERROR) should end with exit(1), not send
* control back to the sigsetjmp block above
*/
ExitOnAnyError = true;
/* Close down the database */
ShutdownXLOG(0, 0);
/* Normal exit from the checkpointer is here */
proc_exit(0); /* done */
}
HandleCheckpointerInterrupts();
/*
* Detect a pending checkpoint request by checking whether the flags
@ -558,6 +529,44 @@ CheckpointerMain(void)
}
}
/*
* Process any new interrupts.
*/
static void
HandleCheckpointerInterrupts(void)
{
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
/*
* Checkpointer is the last process to shut down, so we ask it to
* hold the keys for a range of other tasks required most of which
* have nothing to do with checkpointing at all.
*
* For various reasons, some config values can change dynamically
* so the primary copy of them is held in shared memory to make
* sure all backends see the same value. We make Checkpointer
* responsible for updating the shared memory copy if the
* parameter setting changes because of SIGHUP.
*/
UpdateSharedMemoryConfig();
}
if (shutdown_requested)
{
/*
* From here on, elog(ERROR) should end with exit(1), not send
* control back to the sigsetjmp block above
*/
ExitOnAnyError = true;
/* Close down the database */
ShutdownXLOG(0, 0);
/* Normal exit from the checkpointer is here */
proc_exit(0); /* done */
}
}
/*
* CheckArchiveTimeout -- check for archive_timeout and switch xlog files
*

View File

@ -83,6 +83,8 @@ int WalWriterFlushAfter = 128;
static volatile sig_atomic_t got_SIGHUP = false;
static volatile sig_atomic_t shutdown_requested = false;
static void HandleWalWriterInterrupts(void);
/* Signal handlers */
static void wal_quickdie(SIGNAL_ARGS);
static void WalSigHupHandler(SIGNAL_ARGS);
@ -242,19 +244,7 @@ WalWriterMain(void)
/* Clear any already-pending wakeups */
ResetLatch(MyLatch);
/*
* Process any requests or signals received recently.
*/
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
}
if (shutdown_requested)
{
/* Normal exit from the walwriter is here */
proc_exit(0); /* done */
}
HandleWalWriterInterrupts();
/*
* Do what we're here for; then, if XLogBackgroundFlush() found useful
@ -282,6 +272,24 @@ WalWriterMain(void)
}
}
/*
* Process any new interrupts.
*/
static void
HandleWalWriterInterrupts(void)
{
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
}
if (shutdown_requested)
{
/* Normal exit from the walwriter is here */
proc_exit(0); /* done */
}
}
/* --------------------------------
* signal handler routines