From: Willy Tarreau Date: Thu, 12 Mar 2026 08:35:16 +0000 (+0100) Subject: MINOR: cli: keep track of the initcall context since kw registration X-Git-Tag: v3.4-dev7~49 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5cd71f69ba4a24d92a05499749549fe9ebaf98e3;p=thirdparty%2Fhaproxy.git MINOR: cli: keep track of the initcall context since kw registration Now CLI keywords registered via an initcall will be tracked during execution, by keeping a link to their initcall location. "show threads" now shows "exec_ctx: kw registered at @debug.c:3093" which indeed corresponds to the initcall for the debugging commands. --- diff --git a/include/haproxy/cli-t.h b/include/haproxy/cli-t.h index 3332b6da6..76e935dbb 100644 --- a/include/haproxy/cli-t.h +++ b/include/haproxy/cli-t.h @@ -23,6 +23,7 @@ #define _HAPROXY_CLI_T_H #include +#include /* Access level for a stats socket (appctx->cli_ctx.level) */ #define ACCESS_LVL_NONE 0x0000 @@ -120,6 +121,8 @@ struct cli_kw { void (*io_release)(struct appctx *appctx); void *private; int level; /* this is the level needed to show the keyword usage and to use it */ + /* 4-byte hole here */ + struct thread_exec_ctx exec_ctx; /* execution context */ }; struct cli_kw_list { diff --git a/src/cli.c b/src/cli.c index f49cca210..a289f1d42 100644 --- a/src/cli.c +++ b/src/cli.c @@ -400,6 +400,18 @@ struct cli_kw* cli_find_kw_exact(char **args) void cli_register_kw(struct cli_kw_list *kw_list) { + struct cli_kw *kw; + + for (kw = &kw_list->kw[0]; kw->str_kw[0]; kw++) { + /* store declaration file/line if known */ + if (kw->exec_ctx.type) + continue; + + if (caller_initcall) { + kw->exec_ctx.type = TH_EX_CTX_INITCALL; + kw->exec_ctx.initcall = caller_initcall; + } + } LIST_APPEND(&cli_keywords.list, &kw_list->list); } @@ -1211,11 +1223,11 @@ void cli_io_handler(struct appctx *appctx) case CLI_ST_CALLBACK: /* use custom pointer */ if (appctx->cli_ctx.io_handler) - if (appctx->cli_ctx.io_handler(appctx)) { + if (EXEC_CTX_WITH_RET(appctx->cli_ctx.kw->exec_ctx, appctx->cli_ctx.io_handler(appctx))) { appctx->t->expire = TICK_ETERNITY; appctx->st0 = CLI_ST_PROMPT; if (appctx->cli_ctx.io_release) { - appctx->cli_ctx.io_release(appctx); + EXEC_CTX_NO_RET(appctx->cli_ctx.kw->exec_ctx, appctx->cli_ctx.io_release(appctx)); appctx->cli_ctx.io_release = NULL; appctx->cli_ctx.kw = NULL; /* some release handlers might have @@ -1329,7 +1341,7 @@ static void cli_release_handler(struct appctx *appctx) free_trash_chunk(appctx->cli_ctx.cmdline); if (appctx->cli_ctx.io_release) { - appctx->cli_ctx.io_release(appctx); + EXEC_CTX_NO_RET(appctx->cli_ctx.kw->exec_ctx, appctx->cli_ctx.io_release(appctx)); appctx->cli_ctx.io_release = NULL; appctx->cli_ctx.kw = NULL; }