From 7a7eada6f4ecfc54325a18cf20c3035994a901c4 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 25 Oct 2016 16:49:31 +0200 Subject: [PATCH 13/26] BUG/MINOR: systemd: always restore signals before execve() Since signals are inherited, we must restore them before calling execve() and intercept them again after a failed execve(). In order to cleanly deal with the SIGUSR2/SIGHUP loops where we re-exec the wrapper, we ignore these two signals during a re-exec, and restore them to defaults when spawning haproxy. This should be backported to 1.6 and 1.5. (cherry picked from commit 4351ea61fbddf88c960179d60b0e0f1b090f0b70) --- src/haproxy-systemd-wrapper.c | 49 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/haproxy-systemd-wrapper.c b/src/haproxy-systemd-wrapper.c index a78e75b..84d2e17 100644 --- a/src/haproxy-systemd-wrapper.c +++ b/src/haproxy-systemd-wrapper.c @@ -28,6 +28,11 @@ static char *pid_file = "/run/haproxy.pid"; static int wrapper_argc; static char **wrapper_argv; +static void setup_signal_handler(); +static void pause_signal_handler(); +static void reset_signal_handler(); + + /* returns the path to the haproxy binary into , whose size indicated * in must be at least 1 byte long. */ @@ -76,6 +81,8 @@ static void spawn_haproxy(char **pid_strv, int nb_pid) char **argv = calloc(4 + main_argc + nb_pid + 1, sizeof(char *)); int i; int argno = 0; + + reset_signal_handler(); locate_haproxy(haproxy_bin, 512); argv[argno++] = haproxy_bin; for (i = 0; i < main_argc; ++i) @@ -127,6 +134,34 @@ static void signal_handler(int signum) caught_signal = signum; } +static void setup_signal_handler() +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = &signal_handler; + sigaction(SIGUSR2, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); +} + +static void pause_signal_handler() +{ + signal(SIGUSR2, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +} + +static void reset_signal_handler() +{ + signal(SIGUSR2, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +} + /* handles SIGUSR2 and SIGHUP only */ static void do_restart(int sig) { @@ -134,7 +169,11 @@ static void do_restart(int sig) fprintf(stderr, SD_NOTICE "haproxy-systemd-wrapper: re-executing on %s.\n", sig == SIGUSR2 ? "SIGUSR2" : "SIGHUP"); + /* don't let the other process take one of those signals by accident */ + pause_signal_handler(); execv(wrapper_argv[0], wrapper_argv); + /* failed, let's reinstall the signal handler and continue */ + setup_signal_handler(); } /* handles SIGTERM and SIGINT only */ @@ -168,7 +207,8 @@ static void init(int argc, char **argv) int main(int argc, char **argv) { int status; - struct sigaction sa; + + setup_signal_handler(); wrapper_argc = argc; wrapper_argv = argv; @@ -176,13 +216,6 @@ int main(int argc, char **argv) --argc; ++argv; init(argc, argv); - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_handler = &signal_handler; - sigaction(SIGUSR2, &sa, NULL); - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - if (getenv(REEXEC_FLAG) != NULL) { /* We are being re-executed: restart HAProxy gracefully */ int i; -- 2.7.3