]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: cli: store active CLI sessions in a global list
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 9 Nov 2026 09:10:34 +0000 (10:10 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 9 Nov 2026 16:15:29 +0000 (17:15 +0100)
Implement a global list of the currently active CLI sessions. This is
sound as since only one CLI frontend exists per HAProxy instance (via
"stats socket" for a worker, or alternatively a master CLI via -S for a
master process).

Each session is appended in the CLI_ST_INIT state at the beginning of
cli_io_handler() and removed in cli_release_handler().

This will allow to implement new CLI commands which can interact with
other CLI sessions.

include/haproxy/applet-t.h
src/cli.c

index ff41fdf82a34765d0bc5e50aea63f6dceec453cf..9a9268f98006ccdd83afe9385cdda9df389423ac 100644 (file)
@@ -136,6 +136,7 @@ struct appctx {
                void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK,
                                                              if the command is terminated or the session released */
                struct cli_kw *kw;      /* the keyword being processed */
+               struct mt_list sess_el; /* attach point in global <cli_session_list> */
        } cli_ctx; /* context dedicated to the CLI applet */
 
        struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */
index e861c03034dd681dbc0a42684e0573c890780b90..edd20b3a65e11c710bc277503aed64453d6c229b 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -96,6 +96,9 @@ struct show_env_ctx {
        int show_one;    /* stop after showing the first one */
 };
 
+/* Currently active CLI sessions. */
+static struct mt_list cli_session_list = MT_LIST_HEAD_INIT(cli_session_list);
+
 /* CLI context for the "show fd" command */
 /* flags for show_fd_ctx->show_mask */
 #define CLI_SHOWFD_F_PI  0x00000001   /* pipes             */
@@ -1011,6 +1014,7 @@ int cli_init(struct appctx *appctx)
        appctx->cli_ctx.cmdline = NULL;
        appctx->cli_ctx.payload = BUF_NULL;
        appctx->cli_ctx.max_payload_sz = global.tune.cli_max_payload_sz;
+       MT_LIST_APPEND(&cli_session_list, &appctx->cli_ctx.sess_el);
 
        /* Wakeup the applet ASAP. */
         applet_need_more_data(appctx);
@@ -1275,6 +1279,11 @@ void cli_io_handler(struct appctx *appctx)
 {
        appctx->st1 &= ~APPCTX_CLI_ST1_YIELD;
 
+       if (appctx->st0 == CLI_ST_INIT) {
+               /* Init global CLI sess list attach element. Ensure safe delete in release handler. */
+               MT_LIST_INIT(&appctx->cli_ctx.sess_el);
+       }
+
        if (unlikely(applet_fl_test(appctx, APPCTX_FL_EOS|APPCTX_FL_ERROR))) {
                appctx->st0 = CLI_ST_END;
                goto out;
@@ -1523,6 +1532,10 @@ static void cli_release_handler(struct appctx *appctx)
        else if (appctx->st0 == CLI_ST_PRINT_UMSG || appctx->st0 == CLI_ST_PRINT_UMSGERR) {
                usermsgs_clr(NULL);
        }
+
+       /* Removes from global list unless release is called early before first cli_io_handler() invocation. */
+       if (appctx->st0 > CLI_ST_INIT)
+               MT_LIST_DELETE(&appctx->cli_ctx.sess_el);
 }
 
 /* This function dumps all environment variables to the buffer. It returns 0