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 */
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 */
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);
{
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;
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