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