Partially deduplicate interrupt handling for background processes.
authorRobert Haas <[email protected]>
Tue, 17 Dec 2019 18:14:28 +0000 (13:14 -0500)
committerRobert Haas <[email protected]>
Tue, 17 Dec 2019 18:14:28 +0000 (13:14 -0500)
Where possible, share signal handler code and main loop interrupt
checking. This saves quite a bit of code and should simplify
maintenance, too.

This commit intends not to change the way anything works, even
though that might allow more code to be unified. It does unify
a bunch of individual variables into a ShutdownRequestPending
flag that has is now used by a bunch of different process types,
though.

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

Discussion: http://postgr.es/m/CA+TgmoZwDk=BguVDVa+qdA6SBKef=PKbaKDQALTC_9qoz1mJqg@mail.gmail.com

18 files changed:
src/backend/postmaster/Makefile
src/backend/postmaster/autovacuum.c
src/backend/postmaster/bgworker.c
src/backend/postmaster/bgwriter.c
src/backend/postmaster/checkpointer.c
src/backend/postmaster/interrupt.c [new file with mode: 0644]
src/backend/postmaster/pgarch.c
src/backend/postmaster/pgstat.c
src/backend/postmaster/startup.c
src/backend/postmaster/walwriter.c
src/backend/replication/logical/launcher.c
src/backend/replication/logical/worker.c
src/backend/replication/walreceiver.c
src/backend/replication/walsender.c
src/backend/tcop/postgres.c
src/backend/utils/init/globals.c
src/include/miscadmin.h
src/include/postmaster/interrupt.h [new file with mode: 0644]

index 03e3d3650aeacb8e6572e9e89108ad7dd1ef2141..bfdf6a833db3d20be06203ad4373ad3762b2e86c 100644 (file)
@@ -18,6 +18,7 @@ OBJS = \
        bgwriter.o \
        checkpointer.o \
        fork_process.o \
+       interrupt.o \
        pgarch.o \
        pgstat.o \
        postmaster.o \
index b1c2b0a01c23d8d8317a90a3f34221bb5e19f6d3..1792008ebe51cdddda484fa0f7cbede4c215edfe 100644 (file)
@@ -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
index 5f8a007e73cfd0bce3d6fe7aa6b51618b0db249d..a4c347d52461cec2c3b42a129893423b1f7dbb89 100644 (file)
 
 #include "postgres.h"
 
-#include <unistd.h>
-
 #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);
index bca46de6d563d6a0396c488eb75078a4db3d42a0..9cc343b74f5a3e664415c8000e6ce648b634e5f4 100644 (file)
  */
 #include "postgres.h"
 
-#include <signal.h>
-#include <sys/time.h>
-#include <unistd.h>
-
 #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;
-}
index 9cf91b0d35cf27ccd22ce4410205368da2115b9e..3f35b324c33c8aba54ac89c4f74f9440e3db1d6c 100644 (file)
  */
 #include "postgres.h"
 
-#include <signal.h>
 #include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
 
 #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 (file)
index 0000000..6900cd0
--- /dev/null
@@ -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 <unistd.h>
+
+#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;
+}
index 09a9c66b4b274a2e06f221a48a36b506b4e93258..7824180ac7f45c70365ce3a974cff1cb699d6b0a 100644 (file)
@@ -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;
 
                        /*
index 96a9e09cedc6aaa0a2d6df72c8ccc16525028a81..e93151220338c5c7e7a86721827807920804ea24 100644 (file)
@@ -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
  *
index f43e57dadb9ca2e5e2051aae6d48492aa5bacc5f..4f59c71f733af5c97f30d2351186e850e3b68d45 100644 (file)
  */
 #include "postgres.h"
 
-#include <signal.h>
-#include <unistd.h>
-
 #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);
index 599478530f9ddc92df4831c1afb7df78273fbca7..38e9eb1304e841e4e395febc9ec3dd49811cd66d 100644 (file)
@@ -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;
-}
index edca70c58c38db6cfb02697c7eacb39a75937741..99cfa5d8b49c7a08630b37e5808c0e20ac776e80 100644 (file)
@@ -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();
 
index 3b12ad64006f23d7d057df77565f1aefe412f5ab..4bf6f5e4271505cc8b99f450e536dd7d3cad5c76 100644 (file)
@@ -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();
 
index c1e439adb4065e1b8a52bc7e44e834977b01215b..c36bcc08ec76aaa09349a31e8ed6aa5f6b9e9132 100644 (file)
@@ -43,7 +43,6 @@
  */
 #include "postgres.h"
 
-#include <signal.h>
 #include <unistd.h>
 
 #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.
  */
index 8b2a2be1c077c13d2078f5f273c823fcde4962ef..8e74177de4475d9f8d641af42685ecdd6d2884c8 100644 (file)
@@ -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 */
index 0b7bc1fd0307988109c777d186e7e08ab854cff2..ef5a9529689b9a07d41e739b0698728efffca6c4 100644 (file)
@@ -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 */
 
index 3bf96de256df6d06c7fd04dd9287cce10f0a137d..4473e18e53816b2f3b5676571680b375527c4dbc 100644 (file)
@@ -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;
index bc6e03fbc7e89e4f8606fd728751c34b47c6f734..24f43ad6861a9b6a166784def1f235f651bd0252 100644 (file)
@@ -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 (file)
index 0000000..8f4e43b
--- /dev/null
@@ -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 <signal.h>
+
+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