From e57b702e2bd6c0d3787c5996a89ec8513b5c4bc9 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Wed, 7 Dec 2022 14:25:41 +0100 Subject: [PATCH] BUG/MEDIUM: mworker: create the mcli_reload socketpairs in case of upgrade In ticket #1956, it was reported that an upgrade from 2.6 to 2.7 via a reload would stop the master process. When upgrading the binary, the new process is considered reexec and does not try to creates the socketpair for the mcli_reload listener, then tries to bind on -1 since the socket doesn't exit. The failure provokes an exit() of the master. This patch fixes the issue by trying to create the mcli_reload sockets only when they don't exist, instead of creating them at first start. This way we also avoid possible fd leak since we always try to use the existing FDs first. Must be backported in 2.7. --- src/haproxy.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/haproxy.c b/src/haproxy.c index 072526175..7e67f001c 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2132,19 +2132,6 @@ static void init(int argc, char **argv) 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); @@ -2199,6 +2186,21 @@ static void init(int argc, char **argv) free(c->s); free(c); } + /* 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. The sockets are + * created only if they weren't inherited. + */ + if ((proc_self->ipc_fd[1] == -1) && + socketpair(AF_UNIX, SOCK_STREAM, 0, proc_self->ipc_fd) < 0) { + ha_alert("cannot create the mcli_reload socketpair.\n"); + exit(EXIT_FAILURE); + } + /* Create the mcli_reload listener from the proc_self struct */ memprintf(&path, "sockpair@%d", proc_self->ipc_fd[1]); mcli_reload_bind_conf = mworker_cli_proxy_new_listener(path);