Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
isv:cpanel:dev:EA4
scl-php73
0012-0021-PLESK-avoid-child-ignorance.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0012-0021-PLESK-avoid-child-ignorance.patch of Package scl-php73
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Julian Brown <julian.brown@cpanel.net> Date: Tue, 7 May 2019 12:17:48 -0500 Subject: [PATCH 12/14] 0021-PLESK-avoid-child-ignorance Second of 3 patches for signal management. --- sapi/fpm/fpm/fpm_children.c | 9 + sapi/fpm/fpm/fpm_children.c.orig | 486 +++++++++++++++++++++++++++++++ sapi/fpm/fpm/fpm_signals.c | 24 +- sapi/fpm/fpm/fpm_signals.c.orig | 306 +++++++++++++++++++ sapi/fpm/fpm/fpm_signals.h | 1 + sapi/fpm/fpm/fpm_signals.h.orig | 17 ++ 6 files changed, 842 insertions(+), 1 deletion(-) create mode 100644 sapi/fpm/fpm/fpm_children.c.orig create mode 100644 sapi/fpm/fpm/fpm_signals.c.orig create mode 100644 sapi/fpm/fpm/fpm_signals.h.orig diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c index 68c493d..c095665 100644 --- a/sapi/fpm/fpm/fpm_children.c +++ b/sapi/fpm/fpm/fpm_children.c @@ -404,6 +404,11 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to 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_pool_s *wp, int in_event_loop, int nb_to 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 --git a/sapi/fpm/fpm/fpm_children.c.orig b/sapi/fpm/fpm/fpm_children.c.orig new file mode 100644 index 0000000..82c749f --- /dev/null +++ b/sapi/fpm/fpm/fpm_children.c.orig @@ -0,0 +1,486 @@ + /* (c) 2007,2008 Andrei Nigmatulin */ + +#include "fpm_config.h" + +#include <sys/types.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include "fpm.h" +#include "fpm_children.h" +#include "fpm_signals.h" +#include "fpm_worker_pool.h" +#include "fpm_sockets.h" +#include "fpm_process_ctl.h" +#include "fpm_php.h" +#include "fpm_conf.h" +#include "fpm_cleanup.h" +#include "fpm_events.h" +#include "fpm_clock.h" +#include "fpm_stdio.h" +#include "fpm_unix.h" +#include "fpm_env.h" +#include "fpm_scoreboard.h" +#include "fpm_status.h" +#include "fpm_log.h" + +#include "zlog.h" + +static time_t *last_faults; +static int fault; + +static void fpm_children_cleanup(int which, void *arg) /* {{{ */ +{ + free(last_faults); +} +/* }}} */ + +static struct fpm_child_s *fpm_child_alloc() /* {{{ */ +{ + struct fpm_child_s *ret; + + ret = malloc(sizeof(struct fpm_child_s)); + + if (!ret) { + return 0; + } + + memset(ret, 0, sizeof(*ret)); + ret->scoreboard_i = -1; + return ret; +} +/* }}} */ + +static void fpm_child_free(struct fpm_child_s *child) /* {{{ */ +{ + if (child->log_stream) { + zlog_stream_close(child->log_stream); + free(child->log_stream); + } + free(child); +} +/* }}} */ + +static void fpm_child_close(struct fpm_child_s *child, int in_event_loop) /* {{{ */ +{ + if (child->fd_stdout != -1) { + if (in_event_loop) { + fpm_event_fire(&child->ev_stdout); + } + if (child->fd_stdout != -1) { + close(child->fd_stdout); + } + } + + if (child->fd_stderr != -1) { + if (in_event_loop) { + fpm_event_fire(&child->ev_stderr); + } + if (child->fd_stderr != -1) { + close(child->fd_stderr); + } + } + + fpm_child_free(child); +} +/* }}} */ + +static void fpm_child_link(struct fpm_child_s *child) /* {{{ */ +{ + struct fpm_worker_pool_s *wp = child->wp; + + ++wp->running_children; + ++fpm_globals.running_children; + + child->next = wp->children; + if (child->next) { + child->next->prev = child; + } + child->prev = 0; + wp->children = child; +} +/* }}} */ + +static void fpm_child_unlink(struct fpm_child_s *child) /* {{{ */ +{ + --child->wp->running_children; + --fpm_globals.running_children; + + if (child->prev) { + child->prev->next = child->next; + } else { + child->wp->children = child->next; + } + + if (child->next) { + child->next->prev = child->prev; + } +} +/* }}} */ + +static struct fpm_child_s *fpm_child_find(pid_t pid) /* {{{ */ +{ + struct fpm_worker_pool_s *wp; + struct fpm_child_s *child = 0; + + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { + + for (child = wp->children; child; child = child->next) { + if (child->pid == pid) { + break; + } + } + + if (child) break; + } + + if (!child) { + return 0; + } + + return child; +} +/* }}} */ + +static void fpm_child_init(struct fpm_worker_pool_s *wp) /* {{{ */ +{ + fpm_globals.max_requests = wp->config->pm_max_requests; + fpm_globals.listening_socket = dup(wp->listening_socket); + + if (0 > fpm_stdio_init_child(wp) || + 0 > fpm_log_init_child(wp) || + 0 > fpm_status_init_child(wp) || + 0 > fpm_unix_init_child(wp) || + 0 > fpm_signals_init_child() || + 0 > fpm_env_init_child(wp) || + 0 > fpm_php_init_child(wp)) { + + zlog(ZLOG_ERROR, "[pool %s] child failed to initialize", wp->config->name); + exit(FPM_EXIT_SOFTWARE); + } +} +/* }}} */ + +int fpm_children_free(struct fpm_child_s *child) /* {{{ */ +{ + struct fpm_child_s *next; + + for (; child; child = next) { + next = child->next; + fpm_child_close(child, 0 /* in_event_loop */); + } + + return 0; +} +/* }}} */ + +void fpm_children_bury() /* {{{ */ +{ + int status; + pid_t pid; + struct fpm_child_s *child; + + while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { + char buf[128]; + int severity = ZLOG_NOTICE; + int restart_child = 1; + + child = fpm_child_find(pid); + + if (WIFEXITED(status)) { + + snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status)); + + /* if it's been killed because of dynamic process management + * don't restart it automaticaly + */ + if (child && child->idle_kill) { + restart_child = 0; + } + + if (WEXITSTATUS(status) != FPM_EXIT_OK) { + severity = ZLOG_WARNING; + } + + } else if (WIFSIGNALED(status)) { + const char *signame = fpm_signal_names[WTERMSIG(status)]; +#ifdef WCOREDUMP + const char *have_core = WCOREDUMP(status) ? " - core dumped" : ""; +#else + const char* have_core = ""; +#endif + + if (signame == NULL) { + signame = ""; + } + + snprintf(buf, sizeof(buf), "on signal %d (%s%s)", WTERMSIG(status), signame, have_core); + + /* if it's been killed because of dynamic process management + * don't restart it automaticaly + */ + if (child && child->idle_kill && WTERMSIG(status) == SIGQUIT) { + restart_child = 0; + } + + if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */ + severity = ZLOG_WARNING; + } + } else if (WIFSTOPPED(status)) { + + zlog(ZLOG_NOTICE, "child %d stopped for tracing", (int) pid); + + if (child && child->tracer) { + child->tracer(child); + } + + continue; + } + + if (child) { + struct fpm_worker_pool_s *wp = child->wp; + struct timeval tv1, tv2; + + fpm_child_unlink(child); + + fpm_scoreboard_proc_free(wp->scoreboard, child->scoreboard_i); + + fpm_clock_get(&tv1); + + timersub(&tv1, &child->started, &tv2); + + if (restart_child) { + if (!fpm_pctl_can_spawn_children()) { + severity = ZLOG_DEBUG; + } + zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", child->wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec); + } else { + zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process management after %ld.%06d seconds from start", child->wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec); + } + + fpm_child_close(child, 1 /* in event_loop */); + + fpm_pctl_child_exited(); + + if (last_faults && (WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGBUS)) { + time_t now = tv1.tv_sec; + int restart_condition = 1; + int i; + + last_faults[fault++] = now; + + if (fault == fpm_global_config.emergency_restart_threshold) { + fault = 0; + } + + for (i = 0; i < fpm_global_config.emergency_restart_threshold; i++) { + if (now - last_faults[i] > fpm_global_config.emergency_restart_interval) { + restart_condition = 0; + break; + } + } + + if (restart_condition) { + + zlog(ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval); + + fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET); + } + } + + if (restart_child) { + fpm_children_make(wp, 1 /* in event loop */, 1, 0); + + if (fpm_globals.is_child) { + break; + } + } + } else { + zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s. Please open a bug report (https://bugs.php.net).", pid, buf); + } + } +} +/* }}} */ + +static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /* {{{ */ +{ + struct fpm_child_s *c; + + c = fpm_child_alloc(); + + if (!c) { + zlog(ZLOG_ERROR, "[pool %s] unable to malloc new child", wp->config->name); + return 0; + } + + c->wp = wp; + c->fd_stdout = -1; c->fd_stderr = -1; + + if (0 > fpm_stdio_prepare_pipes(c)) { + fpm_child_free(c); + return 0; + } + + if (0 > fpm_scoreboard_proc_alloc(wp->scoreboard, &c->scoreboard_i)) { + fpm_stdio_discard_pipes(c); + fpm_child_free(c); + return 0; + } + + return c; +} +/* }}} */ + +static void fpm_resources_discard(struct fpm_child_s *child) /* {{{ */ +{ + fpm_scoreboard_proc_free(child->wp->scoreboard, child->scoreboard_i); + fpm_stdio_discard_pipes(child); + fpm_child_free(child); +} +/* }}} */ + +static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */ +{ + struct fpm_worker_pool_s *wp; + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { + if (wp == child->wp) { + continue; + } + fpm_scoreboard_free(wp->scoreboard); + } + + fpm_scoreboard_child_use(child->wp->scoreboard, child->scoreboard_i, getpid()); + fpm_stdio_child_use_pipes(child); + fpm_child_free(child); +} +/* }}} */ + +static void fpm_parent_resources_use(struct fpm_child_s *child) /* {{{ */ +{ + fpm_stdio_parent_use_pipes(child); + fpm_child_link(child); +} +/* }}} */ + +int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn, int is_debug) /* {{{ */ +{ + pid_t pid; + struct fpm_child_s *child; + int max; + static int warned = 0; + + if (wp->config->pm == PM_STYLE_DYNAMIC) { + if (!in_event_loop) { /* starting */ + max = wp->config->pm_start_servers; + } else { + max = wp->running_children + nb_to_spawn; + } + } else if (wp->config->pm == PM_STYLE_ONDEMAND) { + if (!in_event_loop) { /* starting */ + max = 0; /* do not create any child at startup */ + } else { + max = wp->running_children + nb_to_spawn; + } + } else { /* PM_STYLE_STATIC */ + max = wp->config->pm_max_children; + } + + /* + * fork children while: + * - fpm_pctl_can_spawn_children : FPM is running in a NORMAL state (aka not restart, stop or reload) + * - wp->running_children < max : there is less than the max process for the current pool + * - (fpm_global_config.process_max < 1 || fpm_globals.running_children < fpm_global_config.process_max): + * if fpm_global_config.process_max is set, FPM has not fork this number of processes (globaly) + */ + while (fpm_pctl_can_spawn_children() && wp->running_children < max && (fpm_global_config.process_max < 1 || fpm_globals.running_children < fpm_global_config.process_max)) { + + warned = 0; + child = fpm_resources_prepare(wp); + + if (!child) { + return 2; + } + + pid = fork(); + + switch (pid) { + + case 0 : + fpm_child_resources_use(child); + fpm_globals.is_child = 1; + fpm_child_init(wp); + return 0; + + case -1 : + zlog(ZLOG_SYSERROR, "fork() failed"); + + fpm_resources_discard(child); + return 2; + + default : + child->pid = pid; + fpm_clock_get(&child->started); + fpm_parent_resources_use(child); + + zlog(is_debug ? ZLOG_DEBUG : ZLOG_NOTICE, "[pool %s] child %d started", wp->config->name, (int) pid); + } + + } + + if (!warned && fpm_global_config.process_max > 0 && fpm_globals.running_children >= fpm_global_config.process_max) { + if (wp->running_children < max) { + warned = 1; + zlog(ZLOG_WARNING, "The maximum number of processes has been reached. Please review your configuration and consider raising 'process.max'"); + } + } + + return 1; /* we are done */ +} +/* }}} */ + +int fpm_children_create_initial(struct fpm_worker_pool_s *wp) /* {{{ */ +{ + if (wp->config->pm == PM_STYLE_ONDEMAND) { + wp->ondemand_event = (struct fpm_event_s *)malloc(sizeof(struct fpm_event_s)); + + if (!wp->ondemand_event) { + zlog(ZLOG_ERROR, "[pool %s] unable to malloc the ondemand socket event", wp->config->name); + // FIXME handle crash + return 1; + } + + memset(wp->ondemand_event, 0, sizeof(struct fpm_event_s)); + fpm_event_set(wp->ondemand_event, wp->listening_socket, FPM_EV_READ | FPM_EV_EDGE, fpm_pctl_on_socket_accept, wp); + wp->socket_event_set = 1; + fpm_event_add(wp->ondemand_event, 0); + + return 1; + } + return fpm_children_make(wp, 0 /* not in event loop yet */, 0, 1); +} +/* }}} */ + +int fpm_children_init_main() /* {{{ */ +{ + if (fpm_global_config.emergency_restart_threshold && + fpm_global_config.emergency_restart_interval) { + + last_faults = malloc(sizeof(time_t) * fpm_global_config.emergency_restart_threshold); + + if (!last_faults) { + return -1; + } + + memset(last_faults, 0, sizeof(time_t) * fpm_global_config.emergency_restart_threshold); + } + + if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_children_cleanup, 0)) { + return -1; + } + + return 0; +} +/* }}} */ diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c index f10dac1..f4bbf60 100644 --- a/sapi/fpm/fpm/fpm_signals.c +++ b/sapi/fpm/fpm/fpm_signals.c @@ -20,6 +20,7 @@ static int sp[2]; static sigset_t block_sigset; +static sigset_t child_block_sigset; const char *fpm_signal_names[NSIG + 1] = { #ifdef SIGHUP @@ -167,7 +168,8 @@ static void sig_handler(int signo) /* {{{ */ if (fpm_globals.parent_pid != getpid()) { /* prevent a signal race condition when child process - have not set up it's own signal handler yet */ + do not set up it's own sigprocmask for some reason, + leads to #76601 in such cases */ return; } @@ -247,6 +249,10 @@ int fpm_signals_init_child() /* {{{ */ } zend_signal_init(); + + if (0 > fpm_signals_unblock()) { + return -1; + } return 0; } /* }}} */ @@ -276,6 +282,12 @@ int fpm_signals_init_mask(int *signum_array, size_t size) /* {{{ */ return -1; } } + memcpy(&child_block_sigset, &block_sigset, sizeof(block_sigset)); + 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; } /* }}} */ @@ -290,6 +302,16 @@ int fpm_signals_block() /* {{{ */ } /* }}} */ +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. diff --git a/sapi/fpm/fpm/fpm_signals.c.orig b/sapi/fpm/fpm/fpm_signals.c.orig new file mode 100644 index 0000000..8d930c0 --- /dev/null +++ b/sapi/fpm/fpm/fpm_signals.c.orig @@ -0,0 +1,306 @@ + /* (c) 2007,2008 Andrei Nigmatulin */ + +#include "fpm_config.h" + +#include <signal.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "fpm.h" +#include "fpm_signals.h" +#include "fpm_sockets.h" +#include "fpm_php.h" +#include "zlog.h" + +static int sp[2]; +static sigset_t block_sigset; + +const char *fpm_signal_names[NSIG + 1] = { +#ifdef SIGHUP + [SIGHUP] = "SIGHUP", +#endif +#ifdef SIGINT + [SIGINT] = "SIGINT", +#endif +#ifdef SIGQUIT + [SIGQUIT] = "SIGQUIT", +#endif +#ifdef SIGILL + [SIGILL] = "SIGILL", +#endif +#ifdef SIGTRAP + [SIGTRAP] = "SIGTRAP", +#endif +#ifdef SIGABRT + [SIGABRT] = "SIGABRT", +#endif +#ifdef SIGEMT + [SIGEMT] = "SIGEMT", +#endif +#ifdef SIGBUS + [SIGBUS] = "SIGBUS", +#endif +#ifdef SIGFPE + [SIGFPE] = "SIGFPE", +#endif +#ifdef SIGKILL + [SIGKILL] = "SIGKILL", +#endif +#ifdef SIGUSR1 + [SIGUSR1] = "SIGUSR1", +#endif +#ifdef SIGSEGV + [SIGSEGV] = "SIGSEGV", +#endif +#ifdef SIGUSR2 + [SIGUSR2] = "SIGUSR2", +#endif +#ifdef SIGPIPE + [SIGPIPE] = "SIGPIPE", +#endif +#ifdef SIGALRM + [SIGALRM] = "SIGALRM", +#endif +#ifdef SIGTERM + [SIGTERM] = "SIGTERM", +#endif +#ifdef SIGCHLD + [SIGCHLD] = "SIGCHLD", +#endif +#ifdef SIGCONT + [SIGCONT] = "SIGCONT", +#endif +#ifdef SIGSTOP + [SIGSTOP] = "SIGSTOP", +#endif +#ifdef SIGTSTP + [SIGTSTP] = "SIGTSTP", +#endif +#ifdef SIGTTIN + [SIGTTIN] = "SIGTTIN", +#endif +#ifdef SIGTTOU + [SIGTTOU] = "SIGTTOU", +#endif +#ifdef SIGURG + [SIGURG] = "SIGURG", +#endif +#ifdef SIGXCPU + [SIGXCPU] = "SIGXCPU", +#endif +#ifdef SIGXFSZ + [SIGXFSZ] = "SIGXFSZ", +#endif +#ifdef SIGVTALRM + [SIGVTALRM] = "SIGVTALRM", +#endif +#ifdef SIGPROF + [SIGPROF] = "SIGPROF", +#endif +#ifdef SIGWINCH + [SIGWINCH] = "SIGWINCH", +#endif +#ifdef SIGINFO + [SIGINFO] = "SIGINFO", +#endif +#ifdef SIGIO + [SIGIO] = "SIGIO", +#endif +#ifdef SIGPWR + [SIGPWR] = "SIGPWR", +#endif +#ifdef SIGSYS + [SIGSYS] = "SIGSYS", +#endif +#ifdef SIGWAITING + [SIGWAITING] = "SIGWAITING", +#endif +#ifdef SIGLWP + [SIGLWP] = "SIGLWP", +#endif +#ifdef SIGFREEZE + [SIGFREEZE] = "SIGFREEZE", +#endif +#ifdef SIGTHAW + [SIGTHAW] = "SIGTHAW", +#endif +#ifdef SIGCANCEL + [SIGCANCEL] = "SIGCANCEL", +#endif +#ifdef SIGLOST + [SIGLOST] = "SIGLOST", +#endif +}; + +static void sig_soft_quit(int signo) /* {{{ */ +{ + int saved_errno = errno; + + /* closing fastcgi listening socket will force fcgi_accept() exit immediately */ + close(0); + if (0 > socket(AF_UNIX, SOCK_STREAM, 0)) { + zlog(ZLOG_WARNING, "failed to create a new socket"); + } + fpm_php_soft_quit(); + errno = saved_errno; +} +/* }}} */ + +static void sig_handler(int signo) /* {{{ */ +{ + static const char sig_chars[NSIG + 1] = { + [SIGTERM] = 'T', + [SIGINT] = 'I', + [SIGUSR1] = '1', + [SIGUSR2] = '2', + [SIGQUIT] = 'Q', + [SIGCHLD] = 'C' + }; + char s; + 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 */ + return; + } + + saved_errno = errno; + s = sig_chars[signo]; + zend_quiet_write(sp[1], &s, sizeof(s)); + errno = saved_errno; +} +/* }}} */ + +int fpm_signals_init_main() /* {{{ */ +{ + struct sigaction act; + + if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) { + zlog(ZLOG_SYSERROR, "failed to init signals: socketpair()"); + return -1; + } + + if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) { + zlog(ZLOG_SYSERROR, "failed to init signals: fd_set_blocked()"); + return -1; + } + + if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) { + zlog(ZLOG_SYSERROR, "falied to init signals: fcntl(F_SETFD, FD_CLOEXEC)"); + return -1; + } + + memset(&act, 0, sizeof(act)); + act.sa_handler = sig_handler; + sigfillset(&act.sa_mask); + + if (0 > sigaction(SIGTERM, &act, 0) || + 0 > sigaction(SIGINT, &act, 0) || + 0 > sigaction(SIGUSR1, &act, 0) || + 0 > sigaction(SIGUSR2, &act, 0) || + 0 > sigaction(SIGCHLD, &act, 0) || + 0 > sigaction(SIGQUIT, &act, 0)) { + + 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; +} +/* }}} */ + +int fpm_signals_init_child() /* {{{ */ +{ + struct sigaction act, act_dfl; + + memset(&act, 0, sizeof(act)); + memset(&act_dfl, 0, sizeof(act_dfl)); + + act.sa_handler = &sig_soft_quit; + act.sa_flags |= SA_RESTART; + + act_dfl.sa_handler = SIG_DFL; + + close(sp[0]); + close(sp[1]); + + if (0 > sigaction(SIGTERM, &act_dfl, 0) || + 0 > sigaction(SIGINT, &act_dfl, 0) || + 0 > sigaction(SIGUSR1, &act_dfl, 0) || + 0 > sigaction(SIGUSR2, &act_dfl, 0) || + 0 > sigaction(SIGCHLD, &act_dfl, 0) || + 0 > sigaction(SIGQUIT, &act, 0)) { + + zlog(ZLOG_SYSERROR, "failed to init child signals: sigaction()"); + return -1; + } + + zend_signal_init(); + return 0; +} +/* }}} */ + +int fpm_signals_get_fd() /* {{{ */ +{ + return sp[0]; +} +/* }}} */ + +int fpm_signals_init_mask(int *signum_array, size_t size) /* {{{ */ +{ + size_t i = 0; + if (0 > sigemptyset(&block_sigset)) { + zlog(ZLOG_SYSERROR, "failed to prepare signal block mask: sigemptyset()"); + return -1; + } + for (i = 0; i < size; ++i) { + int sig_i = signum_array[i]; + if (0 > sigaddset(&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; + } + } + 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_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 --git a/sapi/fpm/fpm/fpm_signals.h b/sapi/fpm/fpm/fpm_signals.h index 6ce7277..ba16ad2 100644 --- a/sapi/fpm/fpm/fpm_signals.h +++ b/sapi/fpm/fpm/fpm_signals.h @@ -10,6 +10,7 @@ int fpm_signals_init_child(); int fpm_signals_get_fd(); int fpm_signals_init_mask(int *signum_array, size_t size); int fpm_signals_block(); +int fpm_signals_child_block(); int fpm_signals_unblock(); extern const char *fpm_signal_names[NSIG + 1]; diff --git a/sapi/fpm/fpm/fpm_signals.h.orig b/sapi/fpm/fpm/fpm_signals.h.orig new file mode 100644 index 0000000..6ce7277 --- /dev/null +++ b/sapi/fpm/fpm/fpm_signals.h.orig @@ -0,0 +1,17 @@ + /* (c) 2007,2008 Andrei Nigmatulin */ + +#ifndef FPM_SIGNALS_H +#define FPM_SIGNALS_H 1 + +#include <signal.h> + +int fpm_signals_init_main(); +int fpm_signals_init_child(); +int fpm_signals_get_fd(); +int fpm_signals_init_mask(int *signum_array, size_t size); +int fpm_signals_block(); +int fpm_signals_unblock(); + +extern const char *fpm_signal_names[NSIG + 1]; + +#endif
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor