summaryrefslogtreecommitdiffstats
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.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c
new file mode 100644
index 0000000..26ed671
--- /dev/null
+++ b/src/backend/libpq/pqsignal.c
@@ -0,0 +1,148 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqsignal.c
+ * Backend signal(2) support (see also src/port/pqsignal.c)
+ *
+ * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/libpq/pqsignal.c
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "libpq/pqsignal.h"
+
+
+/* Global variables */
+sigset_t UnBlockSig,
+ BlockSig,
+ StartupBlockSig;
+
+
+/*
+ * Initialize BlockSig, UnBlockSig, and StartupBlockSig.
+ *
+ * BlockSig is the set of signals to block when we are trying to block
+ * signals. This includes all signals we normally expect to get, but NOT
+ * signals that should never be turned off.
+ *
+ * StartupBlockSig is the set of signals to block during startup packet
+ * collection; it's essentially BlockSig minus SIGTERM, SIGQUIT, SIGALRM.
+ *
+ * UnBlockSig is the set of signals to block when we don't want to block
+ * signals.
+ */
+void
+pqinitmask(void)
+{
+ sigemptyset(&UnBlockSig);
+
+ /* Note: InitializeLatchSupport() modifies UnBlockSig. */
+
+ /* First set all signals, then clear some. */
+ sigfillset(&BlockSig);
+ sigfillset(&StartupBlockSig);
+
+ /*
+ * Unmark those signals that should never be blocked. Some of these signal
+ * names don't exist on all platforms. Most do, but might as well ifdef
+ * them all for consistency...
+ */
+#ifdef SIGTRAP
+ sigdelset(&BlockSig, SIGTRAP);
+ sigdelset(&StartupBlockSig, SIGTRAP);
+#endif
+#ifdef SIGABRT
+ sigdelset(&BlockSig, SIGABRT);
+ sigdelset(&StartupBlockSig, SIGABRT);
+#endif
+#ifdef SIGILL
+ sigdelset(&BlockSig, SIGILL);
+ sigdelset(&StartupBlockSig, SIGILL);
+#endif
+#ifdef SIGFPE
+ sigdelset(&BlockSig, SIGFPE);
+ sigdelset(&StartupBlockSig, SIGFPE);
+#endif
+#ifdef SIGSEGV
+ sigdelset(&BlockSig, SIGSEGV);
+ sigdelset(&StartupBlockSig, SIGSEGV);
+#endif
+#ifdef SIGBUS
+ sigdelset(&BlockSig, SIGBUS);
+ sigdelset(&StartupBlockSig, SIGBUS);
+#endif
+#ifdef SIGSYS
+ sigdelset(&BlockSig, SIGSYS);
+ sigdelset(&StartupBlockSig, SIGSYS);
+#endif
+#ifdef SIGCONT
+ sigdelset(&BlockSig, SIGCONT);
+ sigdelset(&StartupBlockSig, SIGCONT);
+#endif
+
+/* Signals unique to startup */
+#ifdef SIGQUIT
+ sigdelset(&StartupBlockSig, SIGQUIT);
+#endif
+#ifdef SIGTERM
+ sigdelset(&StartupBlockSig, SIGTERM);
+#endif
+#ifdef SIGALRM
+ 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
+}