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 | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/src/haproxy.c b/src/haproxy.c
index 10ddf16..60bd334 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -203,6 +203,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;
@@ -2225,6 +2227,37 @@ static struct task *manage_global_listener_queue(struct 
task *t)
        return t;
 }
 
+void mworker_pipe_handler(int fd)
+{
+       char c;
+
+       while (read(fd, &c, 1) == -1) {
+               if (errno == EINTR)
+                       continue;
+               if (errno == EAGAIN) {
+                       fd_cant_recv(fd);
+                       return;
+               }
+               break;
+       }
+
+       deinit();
+       exit(EXIT_FAILURE);
+       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;
@@ -2475,6 +2508,30 @@ int main(int argc, char **argv)
                        if (ret > 0)
                                exit(0);
                }
+
+               if (global.mode & MODE_MWORKER) {
+                       if ((getenv("HAPROXY_MWORKER_REEXEC") == 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("HAPROXY_MWORKER_PIPE_RD", msg, 
1);
+                                       memprintf(&msg, "%d", mworker_pipe[1]);
+                                       setenv("HAPROXY_MWORKER_PIPE_WR", msg, 
1);
+                                       free(msg);
+                               }
+                       } else {
+                               mworker_pipe[0] = 
atol(getenv("HAPROXY_MWORKER_PIPE_RD"));
+                               mworker_pipe[1] = 
atol(getenv("HAPROXY_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++) {
                        ret = fork();
@@ -2633,6 +2690,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