aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/pqsignal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/pqsignal.c')
-rw-r--r--src/backend/libpq/pqsignal.c49
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
+}