summaryrefslogtreecommitdiff
path: root/src/backend/postmaster/postmaster.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r--src/backend/postmaster/postmaster.c89
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;
}