MEDIUM: mworker/cli: keep the connection of the FD that ask for a reload
When using the "reload" command over the master CLI, all connections to
the master CLI were cut, this was unfortunate because it could have been
used to implement a synchronous reload command.
This patch implements an architecture to keep the connection alive after
the reload.
The master CLI is now equipped with a listener which uses a socketpair,
the 2 FDs of this socketpair are stored in the mworker_proc of the
master, which the master keeps via the environment variable.
ipc_fd[1] is used as a listener for the master CLI. During the "reload"
command, the CLI will send the FD of the current session over ipc_fd[0],
then the reload is achieved, so the master won't handle the recv of the
FD. Once reloaded, ipc_fd[1] receives the FD of the session, so the
connection is preserved. Of course it is a new context, so everything
like the "prompt mode" are lost.
Only the FD which performs the reload is kept.
diff --git a/src/haproxy.c b/src/haproxy.c
index ae2f5eb..a837f48 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2061,6 +2061,19 @@
tmproc->options |= PROC_O_TYPE_MASTER; /* master */
tmproc->pid = pid;
tmproc->timestamp = start_date.tv_sec;
+
+ /* Creates the mcli_reload listener, which is the listener used
+ * to retrieve the master CLI session which asked for the reload.
+ *
+ * ipc_fd[1] will be used as a listener, and ipc_fd[0]
+ * will be used to send the FD of the session.
+ *
+ * Both FDs will be kept in the master.
+ */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, tmproc->ipc_fd) < 0) {
+ ha_alert("cannot create the mcli_reload socketpair.\n");
+ exit(EXIT_FAILURE);
+ }
proc_self = tmproc;
LIST_APPEND(&proc_list, &tmproc->list);
@@ -2098,6 +2111,7 @@
}
if (!LIST_ISEMPTY(&mworker_cli_conf)) {
+ char *path = NULL;
if (mworker_cli_proxy_create() < 0) {
ha_alert("Can't create the master's CLI.\n");
@@ -2114,6 +2128,14 @@
free(c->s);
free(c);
}
+ /* Create the mcli_reload listener from the proc_self struct */
+ memprintf(&path, "sockpair@%d", proc_self->ipc_fd[1]);
+
+ if (mworker_cli_proxy_new_listener(path) < 0) {
+ ha_alert("Cannot create the mcli_reload listener.\n");
+ exit(EXIT_FAILURE);
+ }
+ ha_free(&path);
}
}