This patch ensure that the children will exit when the master quits,
even if the master didn't send any signal.

The master and the workers are connected through a pipe, when the pipe
closes the children leave.
---
 src/haproxy.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/src/haproxy.c b/src/haproxy.c
index d23bf3a..01681d4 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -205,6 +205,8 @@ int *children = NULL; /* store PIDs of children in master 
workers mode */
 static volatile sig_atomic_t caught_signal = 0;
 static char **next_argv = NULL;
 
+int mworker_pipe[2];
+
 /* list of the temporarily limited listeners because of lack of resource */
 struct list global_listener_queue = LIST_HEAD_INIT(global_listener_queue);
 struct task *global_listener_queue_task;
@@ -2227,6 +2229,34 @@ static struct task *manage_global_listener_queue(struct 
task *t)
        return t;
 }
 
+void mworker_pipe_handler(int fd)
+{
+       char c;
+
+       if (read(fd, &c, 1) > -1) {
+               fd_delete(fd);
+               deinit();
+               exit(EXIT_FAILURE);
+       } else {
+               /* should never happened */
+               fd_delete(fd);
+       }
+
+       return;
+}
+
+void mworker_pipe_register(int pipefd[2])
+{
+               close(mworker_pipe[1]); /* close the write end of the master 
pipe in the children */
+
+               fcntl(mworker_pipe[0], F_SETFL, O_NONBLOCK);
+               fdtab[mworker_pipe[0]].owner = mworker_pipe;
+               fdtab[mworker_pipe[0]].iocb = mworker_pipe_handler;
+               fd_insert(mworker_pipe[0]);
+               fd_want_recv(mworker_pipe[0]);
+       }
+
+
 int main(int argc, char **argv)
 {
        int err, retry;
@@ -2478,6 +2508,28 @@ int main(int argc, char **argv)
                                exit(0);
                }
 
+               if (global.mode & MODE_MWORKER) {
+                       if ((getenv(REEXEC_FLAG) == NULL)) {
+                               char *msg = NULL;
+                               /* master pipe to ensure the master is still 
alive  */
+                               ret = pipe(mworker_pipe);
+                               if (ret < 0) {
+                                       Warning("[%s.main()] Cannot create 
master pipe.\n", argv[0]);
+                               } else {
+                                       memprintf(&msg, "%d", mworker_pipe[0]);
+                                       setenv("MWORKER_PIPE_RD", msg, 1);
+                                       memprintf(&msg, "%d", mworker_pipe[1]);
+                                       setenv("MWORKER_PIPE_WR", msg, 1);
+                                       free(msg);
+                               }
+                       } else {
+                               mworker_pipe[0] = 
atol(getenv("MWORKER_PIPE_RD"));
+                               mworker_pipe[1] = 
atol(getenv("MWORKER_PIPE_WR"));
+                               if (mworker_pipe[0] <= 0 || mworker_pipe[1] <= 
0) {
+                                       Warning("[%s.main()] Cannot get master 
pipe FDs.\n", argv[0]);
+                               }
+                       }
+               }
 
                /* the father launches the required number of processes */
                for (proc = 0; proc < global.nbproc; proc++) {
@@ -2637,6 +2689,9 @@ int main(int argc, char **argv)
        if (!dns_init_resolvers(1))
                exit(1);
 
+       if (global.mode & MODE_MWORKER)
+               mworker_pipe_register(mworker_pipe);
+
        protocol_enable_all();
        /*
         * That's it : the central polling loop. Run until we stop.
-- 
2.10.2


Reply via email to