]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: systemd: always restore signals before execve()
authorWilly Tarreau <w@1wt.eu>
Tue, 25 Oct 2016 14:49:31 +0000 (16:49 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 25 Oct 2016 15:36:20 +0000 (17:36 +0200)
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.

src/haproxy-systemd-wrapper.c

index a78e75b369e621a1387b2dadcdfb4b3fef8ae025..84d2e176f96a94e509810024b78a8998b9bafa90 100644 (file)
@@ -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 <buffer>, whose size indicated
  * in <buffer_size> 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;