diff options
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r-- | src/backend/postmaster/postmaster.c | 89 |
1 files changed, 64 insertions, 25 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 6ac4dc3121c..19aa7b765d6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -622,14 +622,25 @@ PostmasterMain(int argc, char *argv[]) /* * Set up signal handlers for the postmaster process. * - * In the postmaster, we want to install non-ignored handlers *without* - * SA_RESTART. This is because they'll be blocked at all times except - * when ServerLoop is waiting for something to happen, and during that - * window, we want signals to exit the select(2) wait so that ServerLoop - * can respond if anything interesting happened. On some platforms, - * signals marked SA_RESTART would not cause the select() wait to end. - * Child processes will generally want SA_RESTART, but we expect them to - * set up their own handlers before unblocking signals. + * In the postmaster, we use pqsignal_pm() rather than pqsignal() (which + * is used by all child processes and client processes). That has a + * couple of special behaviors: + * + * 1. Except on Windows, we tell sigaction() to block all signals for the + * duration of the signal handler. This is faster than our old approach + * of blocking/unblocking explicitly in the signal handler, and it should + * also prevent excessive stack consumption if signals arrive quickly. + * + * 2. We do not set the SA_RESTART flag. This is because signals will be + * blocked at all times except when ServerLoop is waiting for something to + * happen, and during that window, we want signals to exit the select(2) + * wait so that ServerLoop can respond if anything interesting happened. + * On some platforms, signals marked SA_RESTART would not cause the + * select() wait to end. + * + * Child processes will generally want SA_RESTART, so pqsignal() sets that + * flag. We expect children to set up their own handlers before + * unblocking signals. * * CAUTION: when changing this list, check for side-effects on the signal * handling setup of child processes. See tcop/postgres.c, @@ -641,25 +652,21 @@ PostmasterMain(int argc, char *argv[]) pqinitmask(); PG_SETMASK(&BlockSig); - pqsignal_no_restart(SIGHUP, SIGHUP_handler); /* reread config file - * and have children do - * same */ - pqsignal_no_restart(SIGINT, pmdie); /* send SIGTERM and shut down */ - pqsignal_no_restart(SIGQUIT, pmdie); /* send SIGQUIT and die */ - pqsignal_no_restart(SIGTERM, pmdie); /* wait for children and shut - * down */ - pqsignal(SIGALRM, SIG_IGN); /* ignored */ - pqsignal(SIGPIPE, SIG_IGN); /* ignored */ - pqsignal_no_restart(SIGUSR1, sigusr1_handler); /* message from child - * process */ - pqsignal_no_restart(SIGUSR2, dummy_handler); /* unused, reserve for - * children */ - pqsignal_no_restart(SIGCHLD, reaper); /* handle child termination */ - pqsignal(SIGTTIN, SIG_IGN); /* ignored */ - pqsignal(SIGTTOU, SIG_IGN); /* ignored */ + pqsignal_pm(SIGHUP, SIGHUP_handler); /* reread config file and have + * children do same */ + pqsignal_pm(SIGINT, pmdie); /* send SIGTERM and shut down */ + pqsignal_pm(SIGQUIT, pmdie); /* send SIGQUIT and die */ + pqsignal_pm(SIGTERM, pmdie); /* wait for children and shut down */ + pqsignal_pm(SIGALRM, SIG_IGN); /* ignored */ + pqsignal_pm(SIGPIPE, SIG_IGN); /* ignored */ + pqsignal_pm(SIGUSR1, sigusr1_handler); /* message from child process */ + pqsignal_pm(SIGUSR2, dummy_handler); /* unused, reserve for children */ + pqsignal_pm(SIGCHLD, reaper); /* handle child termination */ + pqsignal_pm(SIGTTIN, SIG_IGN); /* ignored */ + pqsignal_pm(SIGTTOU, SIG_IGN); /* ignored */ /* ignore SIGXFSZ, so that ulimit violations work like disk full */ #ifdef SIGXFSZ - pqsignal(SIGXFSZ, SIG_IGN); /* ignored */ + pqsignal_pm(SIGXFSZ, SIG_IGN); /* ignored */ #endif /* @@ -2569,7 +2576,13 @@ SIGHUP_handler(SIGNAL_ARGS) { int save_errno = errno; + /* + * We rely on the signal mechanism to have blocked all signals ... except + * on Windows, which lacks sigaction(), so we have to do it manually. + */ +#ifdef WIN32 PG_SETMASK(&BlockSig); +#endif if (Shutdown <= SmartShutdown) { @@ -2611,7 +2624,9 @@ SIGHUP_handler(SIGNAL_ARGS) #endif } +#ifdef WIN32 PG_SETMASK(&UnBlockSig); +#endif errno = save_errno; } @@ -2625,7 +2640,13 @@ pmdie(SIGNAL_ARGS) { int save_errno = errno; + /* + * We rely on the signal mechanism to have blocked all signals ... except + * on Windows, which lacks sigaction(), so we have to do it manually. + */ +#ifdef WIN32 PG_SETMASK(&BlockSig); +#endif ereport(DEBUG2, (errmsg_internal("postmaster received signal %d", @@ -2745,7 +2766,9 @@ pmdie(SIGNAL_ARGS) break; } +#ifdef WIN32 PG_SETMASK(&UnBlockSig); +#endif errno = save_errno; } @@ -2760,7 +2783,13 @@ reaper(SIGNAL_ARGS) int pid; /* process id of dead child process */ int exitstatus; /* its exit status */ + /* + * We rely on the signal mechanism to have blocked all signals ... except + * on Windows, which lacks sigaction(), so we have to do it manually. + */ +#ifdef WIN32 PG_SETMASK(&BlockSig); +#endif ereport(DEBUG4, (errmsg_internal("reaping dead processes"))); @@ -3061,7 +3090,9 @@ reaper(SIGNAL_ARGS) PostmasterStateMachine(); /* Done with signal handler */ +#ifdef WIN32 PG_SETMASK(&UnBlockSig); +#endif errno = save_errno; } @@ -4975,7 +5006,13 @@ sigusr1_handler(SIGNAL_ARGS) { int save_errno = errno; + /* + * We rely on the signal mechanism to have blocked all signals ... except + * on Windows, which lacks sigaction(), so we have to do it manually. + */ +#ifdef WIN32 PG_SETMASK(&BlockSig); +#endif /* Process background worker state change. */ if (CheckPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE)) @@ -5118,7 +5155,9 @@ sigusr1_handler(SIGNAL_ARGS) signal_child(StartupPID, SIGUSR2); } +#ifdef WIN32 PG_SETMASK(&UnBlockSig); +#endif errno = save_errno; } |