From e20b6a62f853d493c67945880d9f89b6f3b4adbf Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Thu, 1 Jun 2017 17:38:55 +0200 Subject: [PATCH] MEDIUM: mworker: workers exit when the master leaves 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 10ddf1602..60bd334b2 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.