summaryrefslogtreecommitdiff
path: root/src/backend/postmaster/fork_process.c
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2023-01-12 12:34:23 +1300
committerThomas Munro <tmunro@postgresql.org>2023-01-12 16:32:20 +1300
commit7389aad63666a2cac18cd6d7496378d7f50ef37b (patch)
treedfcfb672a82df147e9e73a536332eb7dd5a2770d /src/backend/postmaster/fork_process.c
parentd93d68aeeaeeda0e871825b461fd9ab68c7c0de3 (diff)
Use WaitEventSet API for postmaster's event loop.
Switch to a design similar to regular backends, instead of the previous arrangement where signal handlers did non-trivial state management and called fork(). The main changes are: * The postmaster now has its own local latch to wait on. (For now, we don't want other backends setting its latch directly, but that could probably be made to work with more research on robustness.) * The existing signal handlers are cut in two: a handle_pm_XXX() part that just sets pending_pm_XXX flags and the latch, and a process_pm_XXX() part that runs later when the latch is seen. * Signal handlers are now installed with the regular pqsignal() function rather than the special pqsignal_pm() function; historical portability concerns about the effect of SA_RESTART on select() are no longer relevant, and we don't need to block signals anymore. Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/CA%2BhUKG%2BZ-HpOj1JsO9eWUP%2Bar7npSVinsC_npxSy%2BjdOMsx%3DGg%40mail.gmail.com
Diffstat (limited to 'src/backend/postmaster/fork_process.c')
-rw-r--r--src/backend/postmaster/fork_process.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c
index 569b52e8495..509587636e2 100644
--- a/src/backend/postmaster/fork_process.c
+++ b/src/backend/postmaster/fork_process.c
@@ -12,24 +12,28 @@
#include "postgres.h"
#include <fcntl.h>
+#include <signal.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
+#include "libpq/pqsignal.h"
#include "postmaster/fork_process.h"
#ifndef WIN32
/*
* Wrapper for fork(). Return values are the same as those for fork():
* -1 if the fork failed, 0 in the child process, and the PID of the
- * child in the parent process.
+ * child in the parent process. Signals are blocked while forking, so
+ * the child must unblock.
*/
pid_t
fork_process(void)
{
pid_t result;
const char *oomfilename;
+ sigset_t save_mask;
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
@@ -51,6 +55,13 @@ fork_process(void)
getitimer(ITIMER_PROF, &prof_itimer);
#endif
+ /*
+ * We start postmaster children with signals blocked. This allows them to
+ * install their own handlers before unblocking, to avoid races where they
+ * might run the postmaster's handler and miss an important control signal.
+ * With more analysis this could potentially be relaxed.
+ */
+ sigprocmask(SIG_SETMASK, &BlockSig, &save_mask);
result = fork();
if (result == 0)
{
@@ -103,6 +114,11 @@ fork_process(void)
/* do post-fork initialization for random number generation */
pg_strong_random_init();
}
+ else
+ {
+ /* in parent, restore signal mask */
+ sigprocmask(SIG_SETMASK, &save_mask, NULL);
+ }
return result;
}