220 lines
6.7 KiB
Diff
220 lines
6.7 KiB
Diff
Fix for https://bugs.php.net/74083 master PHP-fpm is stopped on multiple reloads
|
|
backported for 7.4 from
|
|
|
|
From ae5154c6c6af7ba7c592f8af006b7cadd0d66d6e Mon Sep 17 00:00:00 2001
|
|
From: Maksim Nikulin <mnikulin@plesk.com>
|
|
Date: Wed, 24 Jul 2019 16:50:57 +0700
|
|
Subject: [PATCH] Block signals during fpm master initialization
|
|
|
|
From e37bd5dcc2e8f269c6031d86429311c8cf243060 Mon Sep 17 00:00:00 2001
|
|
From: Maksim Nikulin <mnikulin@plesk.com>
|
|
Date: Mon, 21 Oct 2019 14:23:29 +0700
|
|
Subject: [PATCH] Do not let PHP-FPM children miss SIGTERM, SIGQUIT
|
|
|
|
|
|
diff -up ./sapi/fpm/fpm/fpm_children.c.fpmsig ./sapi/fpm/fpm/fpm_children.c
|
|
--- ./sapi/fpm/fpm/fpm_children.c.fpmsig 2020-10-23 10:36:31.423925856 +0200
|
|
+++ ./sapi/fpm/fpm/fpm_children.c 2020-10-23 10:36:38.872900642 +0200
|
|
@@ -404,6 +404,11 @@ int fpm_children_make(struct fpm_worker_
|
|
return 2;
|
|
}
|
|
|
|
+ zlog(ZLOG_DEBUG, "blocking signals before child birth");
|
|
+ if (0 > fpm_signals_child_block()) {
|
|
+ zlog(ZLOG_WARNING, "child may miss signals");
|
|
+ }
|
|
+
|
|
pid = fork();
|
|
|
|
switch (pid) {
|
|
@@ -415,12 +420,16 @@ int fpm_children_make(struct fpm_worker_
|
|
return 0;
|
|
|
|
case -1 :
|
|
+ zlog(ZLOG_DEBUG, "unblocking signals");
|
|
+ fpm_signals_unblock();
|
|
zlog(ZLOG_SYSERROR, "fork() failed");
|
|
|
|
fpm_resources_discard(child);
|
|
return 2;
|
|
|
|
default :
|
|
+ zlog(ZLOG_DEBUG, "unblocking signals, child born");
|
|
+ fpm_signals_unblock();
|
|
child->pid = pid;
|
|
fpm_clock_get(&child->started);
|
|
fpm_parent_resources_use(child);
|
|
diff -up ./sapi/fpm/fpm/fpm_main.c.fpmsig ./sapi/fpm/fpm/fpm_main.c
|
|
--- ./sapi/fpm/fpm/fpm_main.c.fpmsig 2020-10-13 11:27:02.000000000 +0200
|
|
+++ ./sapi/fpm/fpm/fpm_main.c 2020-10-23 10:36:38.873900639 +0200
|
|
@@ -90,6 +90,7 @@ int __riscosify_control = __RISCOSIFY_ST
|
|
#include "fpm.h"
|
|
#include "fpm_request.h"
|
|
#include "fpm_status.h"
|
|
+#include "fpm_signals.h"
|
|
#include "fpm_conf.h"
|
|
#include "fpm_php.h"
|
|
#include "fpm_log.h"
|
|
@@ -1584,6 +1585,11 @@ int main(int argc, char *argv[])
|
|
closes it. in apache|apxs mode apache
|
|
does that for us! thies@thieso.net
|
|
20000419 */
|
|
+
|
|
+ if (0 > fpm_signals_init_mask() || 0 > fpm_signals_block()) {
|
|
+ zlog(ZLOG_WARNING, "Could die in the case of too early reload signal");
|
|
+ }
|
|
+ zlog(ZLOG_DEBUG, "Blocked some signals");
|
|
#endif
|
|
#endif
|
|
|
|
diff -up ./sapi/fpm/fpm/fpm_process_ctl.c.fpmsig ./sapi/fpm/fpm/fpm_process_ctl.c
|
|
--- ./sapi/fpm/fpm/fpm_process_ctl.c.fpmsig 2020-10-13 11:27:02.000000000 +0200
|
|
+++ ./sapi/fpm/fpm/fpm_process_ctl.c 2020-10-23 10:36:11.921991864 +0200
|
|
@@ -77,6 +77,10 @@ static void fpm_pctl_exit() /* {{{ */
|
|
|
|
static void fpm_pctl_exec() /* {{{ */
|
|
{
|
|
+ zlog(ZLOG_DEBUG, "Blocking some signals before reexec");
|
|
+ if (0 > fpm_signals_block()) {
|
|
+ zlog(ZLOG_WARNING, "concurrent reloads may be unstable");
|
|
+ }
|
|
|
|
zlog(ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\""
|
|
"%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
|
|
diff -up ./sapi/fpm/fpm/fpm_signals.c.fpmsig ./sapi/fpm/fpm/fpm_signals.c
|
|
--- ./sapi/fpm/fpm/fpm_signals.c.fpmsig 2020-10-13 11:27:02.000000000 +0200
|
|
+++ ./sapi/fpm/fpm/fpm_signals.c 2020-10-23 10:36:38.873900639 +0200
|
|
@@ -19,6 +19,8 @@
|
|
#include "zlog.h"
|
|
|
|
static int sp[2];
|
|
+static sigset_t block_sigset;
|
|
+static sigset_t child_block_sigset;
|
|
|
|
const char *fpm_signal_names[NSIG + 1] = {
|
|
#ifdef SIGHUP
|
|
@@ -165,8 +167,11 @@ static void sig_handler(int signo) /* {{
|
|
int saved_errno;
|
|
|
|
if (fpm_globals.parent_pid != getpid()) {
|
|
- /* prevent a signal race condition when child process
|
|
- have not set up it's own signal handler yet */
|
|
+ /* Avoid using of signal handlers from the master process in a worker
|
|
+ before the child sets up its own signal handlers.
|
|
+ Normally it is prevented by the sigprocmask() calls
|
|
+ around fork(). This execution branch is a last resort trap
|
|
+ that has no protection against #76601. */
|
|
return;
|
|
}
|
|
|
|
@@ -210,6 +215,11 @@ int fpm_signals_init_main() /* {{{ */
|
|
zlog(ZLOG_SYSERROR, "failed to init signals: sigaction()");
|
|
return -1;
|
|
}
|
|
+
|
|
+ zlog(ZLOG_DEBUG, "Unblocking all signals");
|
|
+ if (0 > fpm_signals_unblock()) {
|
|
+ return -1;
|
|
+ }
|
|
return 0;
|
|
}
|
|
/* }}} */
|
|
@@ -241,6 +251,10 @@ int fpm_signals_init_child() /* {{{ */
|
|
}
|
|
|
|
zend_signal_init();
|
|
+
|
|
+ if (0 > fpm_signals_unblock()) {
|
|
+ return -1;
|
|
+ }
|
|
return 0;
|
|
}
|
|
/* }}} */
|
|
@@ -250,3 +264,72 @@ int fpm_signals_get_fd() /* {{{ */
|
|
return sp[0];
|
|
}
|
|
/* }}} */
|
|
+
|
|
+int fpm_signals_init_mask() /* {{{ */
|
|
+{
|
|
+ /* Subset of signals from fpm_signals_init_main() and fpm_got_signal()
|
|
+ blocked to avoid unexpected death during early init
|
|
+ or during reload just after execvp() or fork */
|
|
+ int init_signal_array[] = { SIGUSR1, SIGUSR2, SIGCHLD };
|
|
+ size_t size = sizeof(init_signal_array)/sizeof(init_signal_array[0]);
|
|
+ size_t i = 0;
|
|
+ if (0 > sigemptyset(&block_sigset) ||
|
|
+ 0 > sigemptyset(&child_block_sigset)) {
|
|
+ zlog(ZLOG_SYSERROR, "failed to prepare signal block mask: sigemptyset()");
|
|
+ return -1;
|
|
+ }
|
|
+ for (i = 0; i < size; ++i) {
|
|
+ int sig_i = init_signal_array[i];
|
|
+ if (0 > sigaddset(&block_sigset, sig_i) ||
|
|
+ 0 > sigaddset(&child_block_sigset, sig_i)) {
|
|
+ if (sig_i <= NSIG && fpm_signal_names[sig_i] != NULL) {
|
|
+ zlog(ZLOG_SYSERROR, "failed to prepare signal block mask: sigaddset(%s)",
|
|
+ fpm_signal_names[sig_i]);
|
|
+ } else {
|
|
+ zlog(ZLOG_SYSERROR, "failed to prepare signal block mask: sigaddset(%d)", sig_i);
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+ if (0 > sigaddset(&child_block_sigset, SIGTERM) ||
|
|
+ 0 > sigaddset(&child_block_sigset, SIGQUIT)) {
|
|
+ zlog(ZLOG_SYSERROR, "failed to prepare child signal block mask: sigaddset()");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+/* }}} */
|
|
+
|
|
+int fpm_signals_block() /* {{{ */
|
|
+{
|
|
+ if (0 > sigprocmask(SIG_BLOCK, &block_sigset, NULL)) {
|
|
+ zlog(ZLOG_SYSERROR, "failed to block signals");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+/* }}} */
|
|
+
|
|
+int fpm_signals_child_block() /* {{{ */
|
|
+{
|
|
+ if (0 > sigprocmask(SIG_BLOCK, &child_block_sigset, NULL)) {
|
|
+ zlog(ZLOG_SYSERROR, "failed to block child signals");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+/* }}} */
|
|
+
|
|
+int fpm_signals_unblock() /* {{{ */
|
|
+{
|
|
+ /* Ensure that during reload after upgrade all signals are unblocked.
|
|
+ block_sigset could have different value before execve() */
|
|
+ sigset_t all_signals;
|
|
+ sigfillset(&all_signals);
|
|
+ if (0 > sigprocmask(SIG_UNBLOCK, &all_signals, NULL)) {
|
|
+ zlog(ZLOG_SYSERROR, "failed to unblock signals");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+/* }}} */
|
|
diff -up ./sapi/fpm/fpm/fpm_signals.h.fpmsig ./sapi/fpm/fpm/fpm_signals.h
|
|
--- ./sapi/fpm/fpm/fpm_signals.h.fpmsig 2020-10-13 11:27:02.000000000 +0200
|
|
+++ ./sapi/fpm/fpm/fpm_signals.h 2020-10-23 10:36:38.873900639 +0200
|
|
@@ -8,6 +8,10 @@
|
|
int fpm_signals_init_main();
|
|
int fpm_signals_init_child();
|
|
int fpm_signals_get_fd();
|
|
+int fpm_signals_init_mask();
|
|
+int fpm_signals_block();
|
|
+int fpm_signals_child_block();
|
|
+int fpm_signals_unblock();
|
|
|
|
extern const char *fpm_signal_names[NSIG + 1];
|
|
|