]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mworker: always stop the receiving listener
authorWilliam Lallemand <wlallemand@haproxy.com>
Thu, 12 Mar 2026 15:49:32 +0000 (16:49 +0100)
committerWilliam Lallemand <wlallemand@haproxy.com>
Thu, 12 Mar 2026 16:29:50 +0000 (17:29 +0100)
Upon _send_status, always stop the listener from which the request
was received, rather than looking it up from the proc_list entry via
fdtab[proc->ipc_fd[0]].owner.

A BUG_ON is added to verify that the listener which received the
request is the one expected for the reported PID.

This means it is no longer possible to send "_send_status READY XXX"
manually through the master CLI for testing, as that would trigger
the BUG_ON.

Must be backported as far as 3.1.

src/cli.c

index ee53961f07ae28768ad53b5aa2859d7856954bc8..104b7175d13bfb959bf3d9ae1cf84c37805b76e1 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -2614,8 +2614,9 @@ static int cli_parse_echo(char **args, char *payload, struct appctx *appctx, voi
 
 static int _send_status(char **args, char *payload, struct appctx *appctx, void *private)
 {
-       struct listener *mproxy_li;
        struct mworker_proc *proc;
+       struct stconn *sc = appctx_sc(appctx);
+       struct listener *mproxy_li = strm_li(__sc_strm(sc));
        char *msg = "READY\n";
        int pid;
 
@@ -2625,19 +2626,18 @@ static int _send_status(char **args, char *payload, struct appctx *appctx, void
        pid = atoi(args[2]);
 
        list_for_each_entry(proc, &proc_list, list) {
+
                /* update status of the new worker */
                if (proc->pid == pid) {
                        proc->options &= ~PROC_O_INIT;
-                       /* the sockpair between the master and the worker is
-                        * used temporarly as a listener to receive
-                        * _send_status. Once it is received we don't want to
-                        * use this FD as a listener anymore, but only as a
-                        * server, to allow only connections from the master to
-                        * the worker for the master CLI */
-                       mproxy_li = fdtab[proc->ipc_fd[0]].owner;
-                       BUG_ON(mproxy_li == NULL);
-                       stop_listener(mproxy_li, 0, 0, 0);
+
+                       /* the proxy used to receive the _send_status must be
+                        * the one corresponding to the PID we received in
+                        * argument */
+                       BUG_ON(proc->ipc_fd[0] < 0);
+                       BUG_ON(mproxy_li != fdtab[proc->ipc_fd[0]].owner);
                }
+
                /* send TERM to workers, which have exceeded max_reloads counter */
                if (max_reloads != -1) {
                        if ((proc->options & PROC_O_TYPE_WORKER) &&
@@ -2649,6 +2649,15 @@ static int _send_status(char **args, char *payload, struct appctx *appctx, void
                }
        }
 
+       /* the sockpair between the master and the worker is
+        * used temporarly as a listener to receive
+        * _send_status. Once it is received we don't want to
+        * use this FD as a listener anymore, but only as a
+        * server, to allow only connections from the master to
+        * the worker for the master CLI */
+       BUG_ON(mproxy_li == NULL);
+       stop_listener(mproxy_li, 0, 0, 0);
+
        /* At this point we are sure, that newly forked worker is started,
         * so we can write our PID in a pidfile, if provided. Master doesn't
         * perform chroot.