diff options
Diffstat (limited to 'src/backend/postmaster/fork_process.c')
-rw-r--r-- | src/backend/postmaster/fork_process.c | 18 |
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; } |