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.
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 @@
 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 @@
 	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 @@
 			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 @@
 	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.