aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/postmaster/postmaster.c29
-rw-r--r--src/include/port.h5
-rw-r--r--src/port/pqsignal.c31
3 files changed, 56 insertions, 9 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index ad5bcfe3390..5a609958896 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -603,6 +603,15 @@ 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.
+ *
* 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,
@@ -613,16 +622,20 @@ PostmasterMain(int argc, char *argv[])
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_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(SIGUSR1, sigusr1_handler); /* message from child process */
- pqsignal(SIGUSR2, dummy_handler); /* unused, reserve for children */
- pqsignal(SIGCHLD, reaper); /* handle child termination */
+ 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 */
/* ignore SIGXFSZ, so that ulimit violations work like disk full */
diff --git a/src/include/port.h b/src/include/port.h
index 455f72338cd..a61e59c8f84 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -462,6 +462,11 @@ extern int pg_mkdir_p(char *path, int omode);
/* port/pqsignal.c */
typedef void (*pqsigfunc) (int signo);
extern pqsigfunc pqsignal(int signo, pqsigfunc func);
+#ifndef WIN32
+extern pqsigfunc pqsignal_no_restart(int signo, pqsigfunc func);
+#else
+#define pqsignal_no_restart(signo, func) pqsignal(signo, func)
+#endif
/* port/quotes.c */
extern char *escape_single_quotes_ascii(const char *src);
diff --git a/src/port/pqsignal.c b/src/port/pqsignal.c
index e5a73f22748..07797f909aa 100644
--- a/src/port/pqsignal.c
+++ b/src/port/pqsignal.c
@@ -32,7 +32,7 @@
#if !defined(WIN32) || defined(FRONTEND)
/*
- * Set up a signal handler for signal "signo"
+ * Set up a signal handler, with SA_RESTART, for signal "signo"
*
* Returns the previous handler.
*/
@@ -58,4 +58,33 @@ pqsignal(int signo, pqsigfunc func)
#endif
}
+/*
+ * Set up a signal handler, without SA_RESTART, for signal "signo"
+ *
+ * Returns the previous handler.
+ *
+ * On Windows, this would be identical to pqsignal(), so don't bother.
+ */
+#ifndef WIN32
+
+pqsigfunc
+pqsignal_no_restart(int signo, pqsigfunc func)
+{
+ struct sigaction act,
+ oact;
+
+ act.sa_handler = func;
+ sigemptyset(&act.sa_mask);
+ 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;
+}
+
+#endif /* !WIN32 */
+
#endif /* !defined(WIN32) || defined(FRONTEND) */