In Master Worker mode, when the reloading of the configuration fail,
the process is exiting leaving the children without their father.

To handle this, we register an exit function with atexit(3), which is
reexecuting the binary in a special mode. This particular mode of
HAProxy don't reload the configuration, it only loops on wait().
---
 src/haproxy.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/src/haproxy.c b/src/haproxy.c
index 2454dfd..61114b6 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -183,6 +183,8 @@ struct chunk trash = { };
  */
 char *swap_buffer = NULL;
 
+int atexit_flag = 0;
+
 int nb_oldpids = 0;
 const int zero = 0;
 const int one = 1;
@@ -594,6 +596,7 @@ static void mworker_wait()
 
                if (exitpid == -1 && errno == ECHILD) {
                        Warning("All workers are left. Leaving... (%d)\n", 
status);
+                       atexit_flag = 0;
                        exit(status); /* parent must leave using the latest 
status code known */
                }
 
@@ -621,6 +624,22 @@ static void mworker_wait()
 }
 
 
+/*
+ * Reexec the process in failure mode, instead of exiting
+ */
+void reexec_on_failure()
+{
+       if (!atexit_flag)
+               return;
+
+       setenv("WAIT_ONLY", "1", 1);
+
+       Warning("Reexecuting Master process in waitpid mode\n");
+       mworker_reload();
+
+       Warning("Failed to reexecute the master processs\n");
+}
+
 
 /*
  * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
@@ -1272,6 +1291,18 @@ static void init(int argc, char **argv)
                (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | 
MODE_VERBOSE
                             | MODE_QUIET | MODE_CHECK | MODE_DEBUG));
 
+       /* Master workers wait mode */
+       if ((global.mode & MODE_MWORKER) && (getenv("WAIT_ONLY") != NULL)) {
+
+               unsetenv("WAIT_ONLY");
+               mworker_wait();
+       }
+
+       if ((global.mode & MODE_MWORKER) && (getenv(REEXEC_FLAG) != NULL)) {
+               atexit_flag = 1;
+               atexit(reexec_on_failure);
+       }
+
        if (change_dir && chdir(change_dir) < 0) {
                Alert("Could not change to directory %s : %s\n", change_dir, 
strerror(errno));
                exit(1);
@@ -2425,9 +2456,13 @@ int main(int argc, char **argv)
 #ifndef OPENSSL_NO_DH
                        ssl_free_dh();
 #endif
-                       exit(0); /* parent must leave */
+                       /* should never get there */
+                       exit(EXIT_FAILURE);
                }
 
+               /* child must never use the atexit function */
+               atexit_flag = 0;
+
                /* Must chroot and setgid/setuid in the children */
                /* chroot if needed */
                if (global.chroot != NULL) {
-- 
2.10.2


Reply via email to