diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile index 03e3d3650a..bfdf6a833d 100644 --- a/src/backend/postmaster/Makefile +++ b/src/backend/postmaster/Makefile @@ -18,6 +18,7 @@ OBJS = \ bgwriter.o \ checkpointer.o \ fork_process.o \ + interrupt.o \ pgarch.o \ pgstat.o \ postmaster.o \ diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index b1c2b0a01c..1792008ebe 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -84,6 +84,7 @@ #include "pgstat.h" #include "postmaster/autovacuum.h" #include "postmaster/fork_process.h" +#include "postmaster/interrupt.h" #include "postmaster/postmaster.h" #include "storage/bufmgr.h" #include "storage/ipc.h" @@ -139,7 +140,6 @@ static bool am_autovacuum_worker = false; /* Flags set by signal handlers */ static volatile sig_atomic_t got_SIGUSR2 = false; -static volatile sig_atomic_t got_SIGTERM = false; /* Comparison points for determining whether freeze_max_age is exceeded */ static TransactionId recentXid; @@ -344,7 +344,6 @@ static void autovac_report_activity(autovac_table *tab); static void autovac_report_workitem(AutoVacuumWorkItem *workitem, const char *nspname, const char *relname); static void avl_sigusr2_handler(SIGNAL_ARGS); -static void avl_sigterm_handler(SIGNAL_ARGS); static void autovac_refresh_stats(void); @@ -450,9 +449,9 @@ AutoVacLauncherMain(int argc, char *argv[]) * backend, so we use the same signal handling. See equivalent code in * tcop/postgres.c. */ - pqsignal(SIGHUP, PostgresSigHupHandler); + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGINT, StatementCancelHandler); - pqsignal(SIGTERM, avl_sigterm_handler); + pqsignal(SIGTERM, SignalHandlerForShutdownRequest); pqsignal(SIGQUIT, quickdie); InitializeTimeouts(); /* establishes SIGALRM handler */ @@ -553,7 +552,7 @@ AutoVacLauncherMain(int argc, char *argv[]) RESUME_INTERRUPTS(); /* if in shutdown mode, no need for anything further; just go away */ - if (got_SIGTERM) + if (ShutdownRequestPending) AutoVacLauncherShutdown(); /* @@ -605,7 +604,7 @@ AutoVacLauncherMain(int argc, char *argv[]) */ if (!AutoVacuumingActive()) { - if (!got_SIGTERM) + if (!ShutdownRequestPending) do_start_worker(); proc_exit(0); /* done */ } @@ -622,7 +621,7 @@ AutoVacLauncherMain(int argc, char *argv[]) rebuild_database_list(InvalidOid); /* loop until shutdown request */ - while (!got_SIGTERM) + while (!ShutdownRequestPending) { struct timeval nap; TimestampTz current_time = 0; @@ -800,7 +799,7 @@ static void HandleAutoVacLauncherInterrupts(void) { /* the normal shutdown case */ - if (got_SIGTERM) + if (ShutdownRequestPending) AutoVacLauncherShutdown(); if (ConfigReloadPending) @@ -1415,18 +1414,6 @@ avl_sigusr2_handler(SIGNAL_ARGS) errno = save_errno; } -/* SIGTERM: time to die */ -static void -avl_sigterm_handler(SIGNAL_ARGS) -{ - int save_errno = errno; - - got_SIGTERM = true; - SetLatch(MyLatch); - - errno = save_errno; -} - /******************************************************************** * AUTOVACUUM WORKER CODE @@ -1525,7 +1512,7 @@ AutoVacWorkerMain(int argc, char *argv[]) * backend, so we use the same signal handling. See equivalent code in * tcop/postgres.c. */ - pqsignal(SIGHUP, PostgresSigHupHandler); + pqsignal(SIGHUP, SignalHandlerForConfigReload); /* * SIGINT is used to signal canceling the current table's vacuum; SIGTERM diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index 5f8a007e73..a4c347d524 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -12,14 +12,13 @@ #include "postgres.h" -#include - #include "access/parallel.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" #include "port/atomics.h" #include "postmaster/bgworker_internals.h" +#include "postmaster/interrupt.h" #include "postmaster/postmaster.h" #include "replication/logicallauncher.h" #include "replication/logicalworker.h" @@ -641,26 +640,6 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel) return true; } -static void -bgworker_quickdie(SIGNAL_ARGS) -{ - /* - * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here - * because shared memory may be corrupted, so we don't want to try to - * clean up our transaction. Just nail the windows shut and get out of - * town. The callbacks wouldn't be safe to run from a signal handler, - * anyway. - * - * Note we do _exit(2) not _exit(0). This is to force the postmaster into - * a system reset cycle if someone sends a manual SIGQUIT to a random - * backend. This is necessary precisely because we don't clean up our - * shared memory state. (The "dead man switch" mechanism in pmsignal.c - * should ensure the postmaster sees this as a crash, too, but no harm in - * being doubly sure.) - */ - _exit(2); -} - /* * Standard SIGTERM handler for background workers */ @@ -754,7 +733,7 @@ StartBackgroundWorker(void) pqsignal(SIGTERM, bgworker_die); pqsignal(SIGHUP, SIG_IGN); - pqsignal(SIGQUIT, bgworker_quickdie); + pqsignal(SIGQUIT, SignalHandlerForCrashExit); InitializeTimeouts(); /* establishes SIGALRM handler */ pqsignal(SIGPIPE, SIG_IGN); diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c index bca46de6d5..9cc343b74f 100644 --- a/src/backend/postmaster/bgwriter.c +++ b/src/backend/postmaster/bgwriter.c @@ -34,16 +34,13 @@ */ #include "postgres.h" -#include -#include -#include - #include "access/xlog.h" #include "access/xlog_internal.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" #include "postmaster/bgwriter.h" +#include "postmaster/interrupt.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" @@ -86,18 +83,6 @@ int BgWriterDelay = 200; static TimestampTz last_snapshot_ts; static XLogRecPtr last_snapshot_lsn = InvalidXLogRecPtr; -/* - * Flags set by interrupt handlers for later service in the main loop. - */ -static volatile sig_atomic_t shutdown_requested = false; - -static void HandleBackgroundWriterInterrupts(void); - -/* Signal handlers */ - -static void bg_quickdie(SIGNAL_ARGS); -static void ReqShutdownHandler(SIGNAL_ARGS); - /* * Main entry point for bgwriter process @@ -116,10 +101,10 @@ BackgroundWriterMain(void) /* * Properly accept or ignore signals that might be sent to us. */ - pqsignal(SIGHUP, PostgresSigHupHandler); /* set flag to read config file */ + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGINT, SIG_IGN); - pqsignal(SIGTERM, ReqShutdownHandler); /* shutdown */ - pqsignal(SIGQUIT, bg_quickdie); /* hard crash time */ + pqsignal(SIGTERM, SignalHandlerForShutdownRequest); + pqsignal(SIGQUIT, SignalHandlerForCrashExit); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); @@ -241,7 +226,7 @@ BackgroundWriterMain(void) /* Clear any already-pending wakeups */ ResetLatch(MyLatch); - HandleBackgroundWriterInterrupts(); + HandleMainLoopInterrupts(); /* * Do one cycle of dirty-buffer writing. @@ -354,71 +339,3 @@ BackgroundWriterMain(void) prev_hibernate = can_hibernate; } } - -/* - * Process any new interrupts. - */ -static void -HandleBackgroundWriterInterrupts(void) -{ - if (ConfigReloadPending) - { - ConfigReloadPending = 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 - * -------------------------------- - */ - -/* - * bg_quickdie() occurs when signalled SIGQUIT by the postmaster. - * - * Some backend has bought the farm, - * so we need to stop what we're doing and exit. - */ -static void -bg_quickdie(SIGNAL_ARGS) -{ - /* - * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here - * because shared memory may be corrupted, so we don't want to try to - * clean up our transaction. Just nail the windows shut and get out of - * town. The callbacks wouldn't be safe to run from a signal handler, - * anyway. - * - * Note we do _exit(2) not _exit(0). This is to force the postmaster into - * a system reset cycle if someone sends a manual SIGQUIT to a random - * backend. This is necessary precisely because we don't clean up our - * shared memory state. (The "dead man switch" mechanism in pmsignal.c - * should ensure the postmaster sees this as a crash, too, but no harm in - * being doubly sure.) - */ - _exit(2); -} - -/* SIGTERM: set flag to shutdown and exit */ -static void -ReqShutdownHandler(SIGNAL_ARGS) -{ - int save_errno = errno; - - shutdown_requested = true; - SetLatch(MyLatch); - - errno = save_errno; -} diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 9cf91b0d35..3f35b324c3 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -36,10 +36,7 @@ */ #include "postgres.h" -#include #include -#include -#include #include "access/xlog.h" #include "access/xlog_internal.h" @@ -47,6 +44,7 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/bgwriter.h" +#include "postmaster/interrupt.h" #include "replication/syncrep.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" @@ -148,11 +146,6 @@ int CheckPointTimeout = 300; int CheckPointWarning = 30; double CheckPointCompletionTarget = 0.5; -/* - * Flags set by interrupt handlers for later service in the main loop. - */ -static volatile sig_atomic_t shutdown_requested = false; - /* * Private state */ @@ -176,10 +169,7 @@ static bool CompactCheckpointerRequestQueue(void); static void UpdateSharedMemoryConfig(void); /* Signal handlers */ - -static void chkpt_quickdie(SIGNAL_ARGS); static void ReqCheckpointHandler(SIGNAL_ARGS); -static void ReqShutdownHandler(SIGNAL_ARGS); /* @@ -204,14 +194,14 @@ CheckpointerMain(void) * want to wait for the backends to exit, whereupon the postmaster will * tell us it's okay to shut down (via SIGUSR2). */ - pqsignal(SIGHUP, PostgresSigHupHandler); /* set flag to read config file */ + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGINT, ReqCheckpointHandler); /* request checkpoint */ pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */ - pqsignal(SIGQUIT, chkpt_quickdie); /* hard crash time */ + pqsignal(SIGQUIT, SignalHandlerForCrashExit); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); - pqsignal(SIGUSR2, ReqShutdownHandler); /* request shutdown */ + pqsignal(SIGUSR2, SignalHandlerForShutdownRequest); /* * Reset some signals that are accepted by postmaster but not here @@ -551,7 +541,7 @@ HandleCheckpointerInterrupts(void) */ UpdateSharedMemoryConfig(); } - if (shutdown_requested) + if (ShutdownRequestPending) { /* * From here on, elog(ERROR) should end with exit(1), not send @@ -679,7 +669,7 @@ CheckpointWriteDelay(int flags, double progress) * in which case we just try to catch up as quickly as possible. */ if (!(flags & CHECKPOINT_IMMEDIATE) && - !shutdown_requested && + !ShutdownRequestPending && !ImmediateCheckpointRequested() && IsCheckpointOnSchedule(progress)) { @@ -807,32 +797,6 @@ IsCheckpointOnSchedule(double progress) * -------------------------------- */ -/* - * chkpt_quickdie() occurs when signalled SIGQUIT by the postmaster. - * - * Some backend has bought the farm, - * so we need to stop what we're doing and exit. - */ -static void -chkpt_quickdie(SIGNAL_ARGS) -{ - /* - * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here - * because shared memory may be corrupted, so we don't want to try to - * clean up our transaction. Just nail the windows shut and get out of - * town. The callbacks wouldn't be safe to run from a signal handler, - * anyway. - * - * Note we do _exit(2) not _exit(0). This is to force the postmaster into - * a system reset cycle if someone sends a manual SIGQUIT to a random - * backend. This is necessary precisely because we don't clean up our - * shared memory state. (The "dead man switch" mechanism in pmsignal.c - * should ensure the postmaster sees this as a crash, too, but no harm in - * being doubly sure.) - */ - _exit(2); -} - /* SIGINT: set flag to run a normal checkpoint right away */ static void ReqCheckpointHandler(SIGNAL_ARGS) @@ -848,18 +812,6 @@ ReqCheckpointHandler(SIGNAL_ARGS) errno = save_errno; } -/* SIGUSR2: set flag to run a shutdown checkpoint and exit */ -static void -ReqShutdownHandler(SIGNAL_ARGS) -{ - int save_errno = errno; - - shutdown_requested = true; - SetLatch(MyLatch); - - errno = save_errno; -} - /* -------------------------------- * communication with backends diff --git a/src/backend/postmaster/interrupt.c b/src/backend/postmaster/interrupt.c new file mode 100644 index 0000000000..6900cd02f6 --- /dev/null +++ b/src/backend/postmaster/interrupt.c @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------- + * + * interrupt.c + * Interrupt handling routines. + * + * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/postmaster/interrupt.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include + +#include "miscadmin.h" +#include "postmaster/interrupt.h" +#include "storage/ipc.h" +#include "storage/latch.h" +#include "utils/guc.h" + +volatile sig_atomic_t ConfigReloadPending = false; +volatile sig_atomic_t ShutdownRequestPending = false; + +/* + * Simple interrupt handler for main loops of background processes. + */ +void +HandleMainLoopInterrupts(void) +{ + if (ConfigReloadPending) + { + ConfigReloadPending = false; + ProcessConfigFile(PGC_SIGHUP); + } + + if (ShutdownRequestPending) + proc_exit(0); +} + +/* + * Simple signal handler for triggering a configuration reload. + * + * Normally, this handler would be used for SIGHUP. The idea is that code + * which uses it would arrange to check the ConfigReloadPending flag at + * convenient places inside main loops, or else call HandleMainLoopInterrupts. + */ +void +SignalHandlerForConfigReload(SIGNAL_ARGS) +{ + int save_errno = errno; + + ConfigReloadPending = true; + SetLatch(MyLatch); + + errno = save_errno; +} + +/* + * Simple signal handler for exiting quickly as if due to a crash. + * + * Normally, this would be used for handling SIGQUIT. + */ +void +SignalHandlerForCrashExit(SIGNAL_ARGS) +{ + /* + * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here + * because shared memory may be corrupted, so we don't want to try to + * clean up our transaction. Just nail the windows shut and get out of + * town. The callbacks wouldn't be safe to run from a signal handler, + * anyway. + * + * Note we do _exit(2) not _exit(0). This is to force the postmaster into + * a system reset cycle if someone sends a manual SIGQUIT to a random + * backend. This is necessary precisely because we don't clean up our + * shared memory state. (The "dead man switch" mechanism in pmsignal.c + * should ensure the postmaster sees this as a crash, too, but no harm in + * being doubly sure.) + */ + _exit(2); +} + +/* + * Simple signal handler for triggering a long-running background process to + * shut down and exit. + * + * Typically, this handler would be used for SIGTERM, but some procesess use + * other signals. In particular, the checkpointer exits on SIGUSR2, the + * stats collector on SIGQUIT, and the WAL writer exits on either SIGINT + * or SIGTERM. + * + * ShutdownRequestPending should be checked at a convenient place within the + * main loop, or else the main loop should call HandleMainLoopInterrupts. + */ +void +SignalHandlerForShutdownRequest(SIGNAL_ARGS) +{ + int save_errno = errno; + + ShutdownRequestPending = true; + SetLatch(MyLatch); + + errno = save_errno; +} diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 09a9c66b4b..7824180ac7 100644 --- a/src/backend/postmaster/pgarch.c +++ b/src/backend/postmaster/pgarch.c @@ -39,6 +39,7 @@ #include "miscadmin.h" #include "pgstat.h" #include "postmaster/fork_process.h" +#include "postmaster/interrupt.h" #include "postmaster/pgarch.h" #include "postmaster/postmaster.h" #include "storage/dsm.h" @@ -83,7 +84,6 @@ static time_t last_sigterm_time = 0; /* * Flags set by interrupt handlers for later service in the main loop. */ -static volatile sig_atomic_t got_SIGTERM = false; static volatile sig_atomic_t wakened = false; static volatile sig_atomic_t ready_to_stop = false; @@ -97,7 +97,6 @@ static pid_t pgarch_forkexec(void); NON_EXEC_STATIC void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn(); static void pgarch_exit(SIGNAL_ARGS); -static void ArchSigTermHandler(SIGNAL_ARGS); static void pgarch_waken(SIGNAL_ARGS); static void pgarch_waken_stop(SIGNAL_ARGS); static void pgarch_MainLoop(void); @@ -227,9 +226,9 @@ PgArchiverMain(int argc, char *argv[]) * Ignore all signals usually bound to some action in the postmaster, * except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT. */ - pqsignal(SIGHUP, PostgresSigHupHandler); + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGINT, SIG_IGN); - pqsignal(SIGTERM, ArchSigTermHandler); + pqsignal(SIGTERM, SignalHandlerForShutdownRequest); pqsignal(SIGQUIT, pgarch_exit); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); @@ -257,24 +256,6 @@ pgarch_exit(SIGNAL_ARGS) exit(1); } -/* SIGTERM signal handler for archiver process */ -static void -ArchSigTermHandler(SIGNAL_ARGS) -{ - int save_errno = errno; - - /* - * The postmaster never sends us SIGTERM, so we assume that this means - * that init is trying to shut down the whole system. If we hang around - * too long we'll get SIGKILL'd. Set flag to prevent starting any more - * archive commands. - */ - got_SIGTERM = true; - SetLatch(MyLatch); - - errno = save_errno; -} - /* SIGUSR1 signal handler for archiver process */ static void pgarch_waken(SIGNAL_ARGS) @@ -346,7 +327,7 @@ pgarch_MainLoop(void) * idea. If more than 60 seconds pass since SIGTERM, exit anyway, so * that the postmaster can start a new archiver if needed. */ - if (got_SIGTERM) + if (ShutdownRequestPending) { time_t curtime = time(NULL); @@ -434,7 +415,7 @@ pgarch_ArchiverCopyLoop(void) * command, and the second is to avoid conflicts with another * archiver spawned by a newer postmaster. */ - if (got_SIGTERM || !PostmasterIsAlive()) + if (ShutdownRequestPending || !PostmasterIsAlive()) return; /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 96a9e09ced..e931512203 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -49,6 +49,7 @@ #include "pgstat.h" #include "postmaster/autovacuum.h" #include "postmaster/fork_process.h" +#include "postmaster/interrupt.h" #include "postmaster/postmaster.h" #include "replication/walsender.h" #include "storage/backendid.h" @@ -262,9 +263,6 @@ static PgStat_GlobalStats globalStats; */ static List *pending_write_requests = NIL; -/* Signal handler flags */ -static volatile bool need_exit = false; - /* * Total time charged to functions so far in the current backend. * We use this to help separate "self" and "other" time charges. @@ -282,7 +280,6 @@ static pid_t pgstat_forkexec(void); #endif NON_EXEC_STATIC void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn(); -static void pgstat_exit(SIGNAL_ARGS); static void pgstat_beshutdown_hook(int code, Datum arg); static PgStat_StatDBEntry *pgstat_get_db_entry(Oid databaseid, bool create); @@ -4432,10 +4429,10 @@ PgstatCollectorMain(int argc, char *argv[]) * except SIGHUP and SIGQUIT. Note we don't need a SIGUSR1 handler to * support latch operations, because we only use a local latch. */ - pqsignal(SIGHUP, PostgresSigHupHandler); + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGINT, SIG_IGN); pqsignal(SIGTERM, SIG_IGN); - pqsignal(SIGQUIT, pgstat_exit); + pqsignal(SIGQUIT, SignalHandlerForShutdownRequest); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, SIG_IGN); @@ -4477,14 +4474,14 @@ PgstatCollectorMain(int argc, char *argv[]) /* * Quit if we get SIGQUIT from the postmaster. */ - if (need_exit) + if (ShutdownRequestPending) break; /* * Inner loop iterates as long as we keep getting messages, or until - * need_exit becomes set. + * ShutdownRequestPending becomes set. */ - while (!need_exit) + while (!ShutdownRequestPending) { /* * Reload configuration if we got SIGHUP from the postmaster. @@ -4676,19 +4673,6 @@ PgstatCollectorMain(int argc, char *argv[]) exit(0); } - -/* SIGQUIT signal handler for collector process */ -static void -pgstat_exit(SIGNAL_ARGS) -{ - int save_errno = errno; - - need_exit = true; - SetLatch(MyLatch); - - errno = save_errno; -} - /* * Subroutine to clear stats in a database entry * diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c index f43e57dadb..4f59c71f73 100644 --- a/src/backend/postmaster/startup.c +++ b/src/backend/postmaster/startup.c @@ -19,13 +19,11 @@ */ #include "postgres.h" -#include -#include - #include "access/xlog.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" +#include "postmaster/interrupt.h" #include "postmaster/startup.h" #include "storage/ipc.h" #include "storage/latch.h" @@ -50,7 +48,6 @@ static volatile sig_atomic_t promote_triggered = false; static volatile sig_atomic_t in_restore_command = false; /* Signal handlers */ -static void startupproc_quickdie(SIGNAL_ARGS); static void StartupProcTriggerHandler(SIGNAL_ARGS); static void StartupProcSigHupHandler(SIGNAL_ARGS); @@ -60,33 +57,6 @@ static void StartupProcSigHupHandler(SIGNAL_ARGS); * -------------------------------- */ -/* - * startupproc_quickdie() occurs when signalled SIGQUIT by the postmaster. - * - * Some backend has bought the farm, - * so we need to stop what we're doing and exit. - */ -static void -startupproc_quickdie(SIGNAL_ARGS) -{ - /* - * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here - * because shared memory may be corrupted, so we don't want to try to - * clean up our transaction. Just nail the windows shut and get out of - * town. The callbacks wouldn't be safe to run from a signal handler, - * anyway. - * - * Note we do _exit(2) not _exit(0). This is to force the postmaster into - * a system reset cycle if someone sends a manual SIGQUIT to a random - * backend. This is necessary precisely because we don't clean up our - * shared memory state. (The "dead man switch" mechanism in pmsignal.c - * should ensure the postmaster sees this as a crash, too, but no harm in - * being doubly sure.) - */ - _exit(2); -} - - /* SIGUSR2: set flag to finish recovery */ static void StartupProcTriggerHandler(SIGNAL_ARGS) @@ -167,7 +137,7 @@ StartupProcessMain(void) pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */ pqsignal(SIGINT, SIG_IGN); /* ignore query cancel */ pqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */ - pqsignal(SIGQUIT, startupproc_quickdie); /* hard crash time */ + pqsignal(SIGQUIT, SignalHandlerForCrashExit); InitializeTimeouts(); /* establishes SIGALRM handler */ pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c index 599478530f..38e9eb1304 100644 --- a/src/backend/postmaster/walwriter.c +++ b/src/backend/postmaster/walwriter.c @@ -48,6 +48,7 @@ #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" +#include "postmaster/interrupt.h" #include "postmaster/walwriter.h" #include "storage/bufmgr.h" #include "storage/condition_variable.h" @@ -77,17 +78,6 @@ int WalWriterFlushAfter = 128; #define LOOPS_UNTIL_HIBERNATE 50 #define HIBERNATE_FACTOR 25 -/* - * Flags set by interrupt handlers for later service in the main loop. - */ -static volatile sig_atomic_t shutdown_requested = false; - -static void HandleWalWriterInterrupts(void); - -/* Signal handlers */ -static void wal_quickdie(SIGNAL_ARGS); -static void WalShutdownHandler(SIGNAL_ARGS); - /* * Main entry point for walwriter process * @@ -108,10 +98,10 @@ WalWriterMain(void) * We have no particular use for SIGINT at the moment, but seems * reasonable to treat like SIGTERM. */ - pqsignal(SIGHUP, PostgresSigHupHandler); /* set flag to read config file */ - pqsignal(SIGINT, WalShutdownHandler); /* request shutdown */ - pqsignal(SIGTERM, WalShutdownHandler); /* request shutdown */ - pqsignal(SIGQUIT, wal_quickdie); /* hard crash time */ + pqsignal(SIGHUP, SignalHandlerForConfigReload); + pqsignal(SIGINT, SignalHandlerForShutdownRequest); + pqsignal(SIGTERM, SignalHandlerForShutdownRequest); + pqsignal(SIGQUIT, SignalHandlerForCrashExit); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); @@ -242,7 +232,7 @@ WalWriterMain(void) /* Clear any already-pending wakeups */ ResetLatch(MyLatch); - HandleWalWriterInterrupts(); + HandleMainLoopInterrupts(); /* * Do what we're here for; then, if XLogBackgroundFlush() found useful @@ -269,65 +259,3 @@ WalWriterMain(void) WAIT_EVENT_WAL_WRITER_MAIN); } } - -/* - * Process any new interrupts. - */ -static void -HandleWalWriterInterrupts(void) -{ - if (ConfigReloadPending) - { - ConfigReloadPending = false; - ProcessConfigFile(PGC_SIGHUP); - } - if (shutdown_requested) - { - /* Normal exit from the walwriter is here */ - proc_exit(0); /* done */ - } -} - - -/* -------------------------------- - * signal handler routines - * -------------------------------- - */ - -/* - * wal_quickdie() occurs when signalled SIGQUIT by the postmaster. - * - * Some backend has bought the farm, - * so we need to stop what we're doing and exit. - */ -static void -wal_quickdie(SIGNAL_ARGS) -{ - /* - * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here - * because shared memory may be corrupted, so we don't want to try to - * clean up our transaction. Just nail the windows shut and get out of - * town. The callbacks wouldn't be safe to run from a signal handler, - * anyway. - * - * Note we do _exit(2) not _exit(0). This is to force the postmaster into - * a system reset cycle if someone sends a manual SIGQUIT to a random - * backend. This is necessary precisely because we don't clean up our - * shared memory state. (The "dead man switch" mechanism in pmsignal.c - * should ensure the postmaster sees this as a crash, too, but no harm in - * being doubly sure.) - */ - _exit(2); -} - -/* SIGTERM: set flag to exit normally */ -static void -WalShutdownHandler(SIGNAL_ARGS) -{ - int save_errno = errno; - - shutdown_requested = true; - SetLatch(MyLatch); - - errno = save_errno; -} diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c index edca70c58c..99cfa5d8b4 100644 --- a/src/backend/replication/logical/launcher.c +++ b/src/backend/replication/logical/launcher.c @@ -30,6 +30,7 @@ #include "pgstat.h" #include "postmaster/bgworker.h" #include "postmaster/fork_process.h" +#include "postmaster/interrupt.h" #include "postmaster/postmaster.h" #include "replication/logicallauncher.h" #include "replication/logicalworker.h" @@ -955,7 +956,7 @@ ApplyLauncherMain(Datum main_arg) LogicalRepCtx->launcher_pid = MyProcPid; /* Establish signal handlers. */ - pqsignal(SIGTERM, PostgresSigHupHandler); + pqsignal(SIGTERM, SignalHandlerForConfigReload); pqsignal(SIGTERM, die); BackgroundWorkerUnblockSignals(); diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 3b12ad6400..4bf6f5e427 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -45,6 +45,7 @@ #include "parser/parse_relation.h" #include "pgstat.h" #include "postmaster/bgworker.h" +#include "postmaster/interrupt.h" #include "postmaster/postmaster.h" #include "postmaster/walwriter.h" #include "replication/decode.h" @@ -1575,7 +1576,7 @@ ApplyWorkerMain(Datum main_arg) logicalrep_worker_attach(worker_slot); /* Setup signal handling */ - pqsignal(SIGHUP, PostgresSigHupHandler); + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGTERM, die); BackgroundWorkerUnblockSignals(); diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index c1e439adb4..c36bcc08ec 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -43,7 +43,6 @@ */ #include "postgres.h" -#include #include #include "access/htup_details.h" @@ -58,6 +57,7 @@ #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" +#include "postmaster/interrupt.h" #include "replication/walreceiver.h" #include "replication/walsender.h" #include "storage/ipc.h" @@ -127,7 +127,6 @@ static void ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime); /* Signal handlers */ static void WalRcvSigHupHandler(SIGNAL_ARGS); static void WalRcvShutdownHandler(SIGNAL_ARGS); -static void WalRcvQuickDieHandler(SIGNAL_ARGS); /* @@ -249,7 +248,7 @@ WalReceiverMain(void) pqsignal(SIGHUP, WalRcvSigHupHandler); /* set flag to read config file */ pqsignal(SIGINT, SIG_IGN); pqsignal(SIGTERM, WalRcvShutdownHandler); /* request shutdown */ - pqsignal(SIGQUIT, WalRcvQuickDieHandler); /* hard crash time */ + pqsignal(SIGQUIT, SignalHandlerForCrashExit); pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); @@ -780,32 +779,6 @@ WalRcvShutdownHandler(SIGNAL_ARGS) errno = save_errno; } -/* - * WalRcvQuickDieHandler() occurs when signalled SIGQUIT by the postmaster. - * - * Some backend has bought the farm, so we need to stop what we're doing and - * exit. - */ -static void -WalRcvQuickDieHandler(SIGNAL_ARGS) -{ - /* - * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here - * because shared memory may be corrupted, so we don't want to try to - * clean up our transaction. Just nail the windows shut and get out of - * town. The callbacks wouldn't be safe to run from a signal handler, - * anyway. - * - * Note we use _exit(2) not _exit(0). This is to force the postmaster - * into a system reset cycle if someone sends a manual SIGQUIT to a random - * backend. This is necessary precisely because we don't clean up our - * shared memory state. (The "dead man switch" mechanism in pmsignal.c - * should ensure the postmaster sees this as a crash, too, but no harm in - * being doubly sure.) - */ - _exit(2); -} - /* * Accept the message from XLOG stream, and process it. */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 8b2a2be1c0..8e74177de4 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -66,6 +66,7 @@ #include "miscadmin.h" #include "nodes/replnodes.h" #include "pgstat.h" +#include "postmaster/interrupt.h" #include "replication/basebackup.h" #include "replication/decode.h" #include "replication/logical.h" @@ -2969,8 +2970,7 @@ void WalSndSignals(void) { /* Set up signal handlers */ - pqsignal(SIGHUP, PostgresSigHupHandler); /* set flag to read config - * file */ + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGINT, StatementCancelHandler); /* query cancel */ pqsignal(SIGTERM, die); /* request shutdown */ pqsignal(SIGQUIT, quickdie); /* hard crash time */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 0b7bc1fd03..ef5a952968 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -58,6 +58,7 @@ #include "pg_trace.h" #include "pgstat.h" #include "postmaster/autovacuum.h" +#include "postmaster/interrupt.h" #include "postmaster/postmaster.h" #include "replication/logicallauncher.h" #include "replication/logicalworker.h" @@ -2861,24 +2862,6 @@ FloatExceptionHandler(SIGNAL_ARGS) "invalid operation, such as division by zero."))); } -/* - * SIGHUP: set flag to re-read config file at next convenient time. - * - * Sets the ConfigReloadPending flag, which should be checked at convenient - * places inside main loops. (Better than doing the reading in the signal - * handler, ey?) - */ -void -PostgresSigHupHandler(SIGNAL_ARGS) -{ - int save_errno = errno; - - ConfigReloadPending = true; - SetLatch(MyLatch); - - errno = save_errno; -} - /* * RecoveryConflictInterrupt: out-of-line portion of recovery conflict * handling following receipt of SIGUSR1. Designed to be similar to die() @@ -3827,8 +3810,7 @@ PostgresMain(int argc, char *argv[], WalSndSignals(); else { - pqsignal(SIGHUP, PostgresSigHupHandler); /* set flag to read config - * file */ + pqsignal(SIGHUP, SignalHandlerForConfigReload); pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */ pqsignal(SIGTERM, die); /* cancel current query and exit */ diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 3bf96de256..4473e18e53 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -32,7 +32,6 @@ volatile sig_atomic_t QueryCancelPending = false; volatile sig_atomic_t ProcDiePending = false; volatile sig_atomic_t ClientConnectionLost = false; volatile sig_atomic_t IdleInTransactionSessionTimeoutPending = false; -volatile sig_atomic_t ConfigReloadPending = false; volatile uint32 InterruptHoldoffCount = 0; volatile uint32 QueryCancelHoldoffCount = 0; volatile uint32 CritSectionCount = 0; diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index bc6e03fbc7..24f43ad686 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -82,7 +82,6 @@ extern PGDLLIMPORT volatile sig_atomic_t InterruptPending; extern PGDLLIMPORT volatile sig_atomic_t QueryCancelPending; extern PGDLLIMPORT volatile sig_atomic_t ProcDiePending; extern PGDLLIMPORT volatile sig_atomic_t IdleInTransactionSessionTimeoutPending; -extern PGDLLIMPORT volatile sig_atomic_t ConfigReloadPending; extern PGDLLIMPORT volatile sig_atomic_t ClientConnectionLost; @@ -279,8 +278,6 @@ extern void restore_stack_base(pg_stack_base_t base); extern void check_stack_depth(void); extern bool stack_is_too_deep(void); -extern void PostgresSigHupHandler(SIGNAL_ARGS); - /* in tcop/utility.c */ extern void PreventCommandIfReadOnly(const char *cmdname); extern void PreventCommandIfParallelMode(const char *cmdname); diff --git a/src/include/postmaster/interrupt.h b/src/include/postmaster/interrupt.h new file mode 100644 index 0000000000..8f4e43be20 --- /dev/null +++ b/src/include/postmaster/interrupt.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * interrupt.h + * Interrupt handling routines. + * + * Responses to interrupts are fairly varied and many types of backends + * have their own implementations, but we provide a few generic things + * here to facilitate code reuse. + * + * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/include/postmaster/interrupt.h + * + *------------------------------------------------------------------------- + */ + +#ifndef INTERRUPT_H +#define INTERRUPT_H + +#include + +extern PGDLLIMPORT volatile sig_atomic_t ConfigReloadPending; +extern PGDLLIMPORT volatile sig_atomic_t ShutdownRequestPending; + +extern void HandleMainLoopInterrupts(void); +extern void SignalHandlerForConfigReload(SIGNAL_ARGS); +extern void SignalHandlerForCrashExit(SIGNAL_ARGS); +extern void SignalHandlerForShutdownRequest(SIGNAL_ARGS); + +#endif