]> granicus.if.org Git - postgresql/commitdiff
Block signals earlier during postmaster startup.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 5 Apr 2014 22:16:11 +0000 (18:16 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 5 Apr 2014 22:16:11 +0000 (18:16 -0400)
Formerly, we set up the postmaster's signal handling only when we were
about to start launching subprocesses.  This is a bad idea though, as
it means that for example a SIGINT arriving before that will kill the
postmaster instantly, perhaps leaving lockfiles, socket files, shared
memory, etc laying about.  We'd rather that such a signal caused orderly
postmaster termination including releasing of those resources.  A simple
fix is to move the PostmasterMain stanza that initializes signal handling
to an earlier point, before we've created any such resources.  Then, an
early-arriving signal will be blocked until we're ready to deal with it
in the usual way.  (The only part that really needs to be moved up is
blocking of signals, but it seems best to keep the signal handler
installation calls together with that; for one thing this ensures the
kernel won't drop any signals we wished to get.  The handlers won't get
invoked in any case until we unblock signals in ServerLoop.)

Per a report from MauMau.  He proposed changing the way "pg_ctl stop"
works to deal with this, but that'd just be masking one symptom not
fixing the core issue.

It's been like this since forever, so back-patch to all supported branches.

src/backend/postmaster/postmaster.c

index 1e08a94e22740f56ce4c9c982805bb0f4ced7758..99f98205dd7f7f046cd0b988c335a184403e849b 100644 (file)
@@ -591,6 +591,36 @@ PostmasterMain(int argc, char *argv[])
        /* Initialize paths to installation files */
        getInstallationPaths(argv[0]);
 
+       /*
+        * Set up signal handlers for the postmaster process.
+        *
+        * CAUTION: when changing this list, check for side-effects on the signal
+        * handling setup of child processes.  See tcop/postgres.c,
+        * bootstrap/bootstrap.c, postmaster/bgwriter.c, postmaster/walwriter.c,
+        * postmaster/autovacuum.c, postmaster/pgarch.c, postmaster/pgstat.c,
+        * postmaster/syslogger.c, postmaster/bgworker.c and
+        * postmaster/checkpointer.c.
+        */
+       pqinitmask();
+       PG_SETMASK(&BlockSig);
+
+       pqsignal(SIGHUP, SIGHUP_handler);       /* reread config file and have
+                                                                                * children do same */
+       pqsignal(SIGINT, pmdie);        /* send SIGTERM and shut down */
+       pqsignal(SIGQUIT, pmdie);       /* send SIGQUIT and die */
+       pqsignal(SIGTERM, pmdie);       /* wait for children and shut down */
+       pqsignal(SIGALRM, SIG_IGN); /* ignored */
+       pqsignal(SIGPIPE, SIG_IGN); /* ignored */
+       pqsignal(SIGUSR1, sigusr1_handler); /* message from child process */
+       pqsignal(SIGUSR2, dummy_handler);       /* unused, reserve for children */
+       pqsignal(SIGCHLD, reaper);      /* handle child termination */
+       pqsignal(SIGTTIN, SIG_IGN); /* ignored */
+       pqsignal(SIGTTOU, SIG_IGN); /* ignored */
+       /* ignore SIGXFSZ, so that ulimit violations work like disk full */
+#ifdef SIGXFSZ
+       pqsignal(SIGXFSZ, SIG_IGN); /* ignored */
+#endif
+
        /*
         * Options setup
         */
@@ -1139,36 +1169,6 @@ PostmasterMain(int argc, char *argv[])
                on_proc_exit(unlink_external_pid_file, 0);
        }
 
-       /*
-        * Set up signal handlers for the postmaster process.
-        *
-        * CAUTION: when changing this list, check for side-effects on the signal
-        * handling setup of child processes.  See tcop/postgres.c,
-        * bootstrap/bootstrap.c, postmaster/bgwriter.c, postmaster/walwriter.c,
-        * postmaster/autovacuum.c, postmaster/pgarch.c, postmaster/pgstat.c,
-        * postmaster/syslogger.c, postmaster/bgworker.c and
-        * postmaster/checkpointer.c.
-        */
-       pqinitmask();
-       PG_SETMASK(&BlockSig);
-
-       pqsignal(SIGHUP, SIGHUP_handler);       /* reread config file and have
-                                                                                * children do same */
-       pqsignal(SIGINT, pmdie);        /* send SIGTERM and shut down */
-       pqsignal(SIGQUIT, pmdie);       /* send SIGQUIT and die */
-       pqsignal(SIGTERM, pmdie);       /* wait for children and shut down */
-       pqsignal(SIGALRM, SIG_IGN); /* ignored */
-       pqsignal(SIGPIPE, SIG_IGN); /* ignored */
-       pqsignal(SIGUSR1, sigusr1_handler); /* message from child process */
-       pqsignal(SIGUSR2, dummy_handler);       /* unused, reserve for children */
-       pqsignal(SIGCHLD, reaper);      /* handle child termination */
-       pqsignal(SIGTTIN, SIG_IGN); /* ignored */
-       pqsignal(SIGTTOU, SIG_IGN); /* ignored */
-       /* ignore SIGXFSZ, so that ulimit violations work like disk full */
-#ifdef SIGXFSZ
-       pqsignal(SIGXFSZ, SIG_IGN); /* ignored */
-#endif
-
        /*
         * If enabled, start up syslogger collection subprocess
         */