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.
This commit is contained in:
William Lallemand 2017-06-01 17:38:55 +02:00 committed by Willy Tarreau
parent 69f9b3bfa4
commit e20b6a62f8

View File

@ -203,6 +203,8 @@ int *children = NULL; /* store PIDs of children in master workers mode */
static volatile sig_atomic_t caught_signal = 0; static volatile sig_atomic_t caught_signal = 0;
static char **next_argv = NULL; static char **next_argv = NULL;
int mworker_pipe[2];
/* list of the temporarily limited listeners because of lack of resource */ /* list of the temporarily limited listeners because of lack of resource */
struct list global_listener_queue = LIST_HEAD_INIT(global_listener_queue); struct list global_listener_queue = LIST_HEAD_INIT(global_listener_queue);
struct task *global_listener_queue_task; struct task *global_listener_queue_task;
@ -2225,6 +2227,37 @@ static struct task *manage_global_listener_queue(struct task *t)
return 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 main(int argc, char **argv)
{ {
int err, retry; int err, retry;
@ -2475,6 +2508,30 @@ int main(int argc, char **argv)
if (ret > 0) if (ret > 0)
exit(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 */ /* the father launches the required number of processes */
for (proc = 0; proc < global.nbproc; proc++) { for (proc = 0; proc < global.nbproc; proc++) {
ret = fork(); ret = fork();
@ -2633,6 +2690,9 @@ int main(int argc, char **argv)
if (!dns_init_resolvers(1)) if (!dns_init_resolvers(1))
exit(1); exit(1);
if (global.mode & MODE_MWORKER)
mworker_pipe_register(mworker_pipe);
protocol_enable_all(); protocol_enable_all();
/* /*
* That's it : the central polling loop. Run until we stop. * That's it : the central polling loop. Run until we stop.