diff --git a/src/haproxy.c b/src/haproxy.c index 1f40a1283..c196d5132 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -181,6 +181,8 @@ struct chunk trash = { }; */ char *swap_buffer = NULL; +int atexit_flag = 0; + int nb_oldpids = 0; const int zero = 0; const int one = 1; @@ -592,6 +594,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 */ } @@ -619,6 +622,22 @@ static void mworker_wait() } +/* + * Reexec the process in failure mode, instead of exiting + */ +void reexec_on_failure() +{ + if (!atexit_flag) + return; + + setenv("HAPROXY_MWORKER_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 @@ -1270,6 +1289,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("HAPROXY_MWORKER_WAIT_ONLY") != NULL)) { + + unsetenv("HAPROXY_MWORKER_WAIT_ONLY"); + mworker_wait(); + } + + if ((global.mode & MODE_MWORKER) && (getenv("HAPROXY_MWORKER_REEXEC") != 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); @@ -2422,9 +2453,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) {