diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-10-13 15:48:26 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-10-13 15:48:26 -0400 |
commit | 9abb2bfc046070b22e3be28173a0736da31cab5a (patch) | |
tree | 436d534545df7601feb65f98c37221e68982b255 /src/backend/libpq/pqsignal.c | |
parent | f38291e927fa8c04eb772e6a17a3dd44da2b69e8 (diff) | |
download | postgresql-9abb2bfc046070b22e3be28173a0736da31cab5a.tar.gz postgresql-9abb2bfc046070b22e3be28173a0736da31cab5a.zip |
In the postmaster, rely on the signal infrastructure to block signals.
POSIX sigaction(2) can be told to block a set of signals while a
signal handler executes. Make use of that instead of manually
blocking and unblocking signals in the postmaster's signal handlers.
This should save a few cycles, and it also prevents recursive
invocation of signal handlers when many signals arrive in close
succession. We have seen buildfarm failures that seem to be due to
postmaster stack overflow caused by such recursion (exacerbated by
a Linux PPC64 kernel bug).
This doesn't change anything about the way that it works on Windows.
Somebody might consider adjusting port/win32/signal.c to let it work
similarly, but I'm not in a position to do that.
For the moment, just apply to HEAD. Possibly we should consider
back-patching this, but it'd be good to let it age awhile first.
Discussion: https://postgr.es/m/14878.1570820201@sss.pgh.pa.us
Diffstat (limited to 'src/backend/libpq/pqsignal.c')
-rw-r--r-- | src/backend/libpq/pqsignal.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c index 68c32bb60d7..4f47eaf2e3a 100644 --- a/src/backend/libpq/pqsignal.c +++ b/src/backend/libpq/pqsignal.c @@ -95,3 +95,52 @@ pqinitmask(void) sigdelset(&StartupBlockSig, SIGALRM); #endif } + +/* + * Set up a postmaster signal handler for signal "signo" + * + * Returns the previous handler. + * + * This is used only in the postmaster, which has its own odd approach to + * signal handling. For signals with handlers, we block all signals for the + * duration of signal handler execution. We also do not set the SA_RESTART + * flag; this should be safe given the tiny range of code in which the + * postmaster ever unblocks signals. + * + * pqinitmask() must have been invoked previously. + * + * On Windows, this function is just an alias for pqsignal() + * (and note that it's calling the code in src/backend/port/win32/signal.c, + * not src/port/pqsignal.c). On that platform, the postmaster's signal + * handlers still have to block signals for themselves. + */ +pqsigfunc +pqsignal_pm(int signo, pqsigfunc func) +{ +#ifndef WIN32 + struct sigaction act, + oact; + + act.sa_handler = func; + if (func == SIG_IGN || func == SIG_DFL) + { + /* in these cases, act the same as pqsignal() */ + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + } + else + { + act.sa_mask = BlockSig; + act.sa_flags = 0; + } +#ifdef SA_NOCLDSTOP + if (signo == SIGCHLD) + act.sa_flags |= SA_NOCLDSTOP; +#endif + if (sigaction(signo, &act, &oact) < 0) + return SIG_ERR; + return oact.sa_handler; +#else /* WIN32 */ + return pqsignal(signo, func); +#endif +} |