diff --git a/include/proto/applet.h b/include/proto/applet.h index b256816b5..81c20e11a 100644 --- a/include/proto/applet.h +++ b/include/proto/applet.h @@ -40,6 +40,7 @@ void applet_run_active(); static inline void appctx_init(struct appctx *appctx) { appctx->st0 = appctx->st1 = appctx->st2 = 0; + appctx->io_release = NULL; } /* Tries to allocate a new appctx and initialize its main fields. The appctx diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h index db60bab83..12f972c6f 100644 --- a/include/proto/dumpstats.h +++ b/include/proto/dumpstats.h @@ -413,8 +413,10 @@ struct cli_kw { const char *str_kw[5]; /* keywords ended by NULL, limited to 5 separated keywords combination */ const char *usage; /* usage message */ - int (*parse)(char **args, struct appctx *appctx); + int (*parse)(char **args, struct appctx *appctx, void *private); int (*io_handler)(struct appctx *appctx); + void (*io_release)(struct appctx *appctx); + void *private; }; struct cli_kw_list { diff --git a/include/types/applet.h b/include/types/applet.h index 1f094e6ba..e60b08a3d 100644 --- a/include/types/applet.h +++ b/include/types/applet.h @@ -55,6 +55,8 @@ struct appctx { void *owner; /* pointer to upper layer's entity (eg: stream interface) */ struct act_rule *rule; /* rule associated with the applet. */ int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = STAT_CLI_O_CUSTOM */ + void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = STAT_CLI_O_CUSTOM, + if the command is terminated or the session released */ void *private; union { diff --git a/src/dumpstats.c b/src/dumpstats.c index 491b0fe67..5cc09aa22 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -1306,9 +1306,10 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line) appctx->ctx.stats.flags = 0; if ((kw = cli_find_kw(args))) { if (kw->parse) { - if (kw->parse(args, appctx) == 0 && kw->io_handler) { + if (kw->parse(args, appctx, kw->private) == 0 && kw->io_handler) { appctx->st0 = STAT_CLI_O_CUSTOM; appctx->io_handler = kw->io_handler; + appctx->io_release = kw->io_release; } } } else if (strcmp(args[0], "show") == 0) { @@ -2844,8 +2845,13 @@ static void cli_io_handler(struct appctx *appctx) break; case STAT_CLI_O_CUSTOM: /* use custom pointer */ if (appctx->io_handler) - if (appctx->io_handler(appctx)) + if (appctx->io_handler(appctx)) { appctx->st0 = STAT_CLI_PROMPT; + if (appctx->io_release) { + appctx->io_release(appctx); + appctx->io_release = NULL; + } + } break; default: /* abnormal state */ si->flags |= SI_FL_ERR; @@ -6752,6 +6758,10 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si) */ static void cli_release_handler(struct appctx *appctx) { + if (appctx->io_release) { + appctx->io_release(appctx); + appctx->io_release = NULL; + } if (appctx->st0 == STAT_CLI_O_SESS && appctx->st2 == STAT_ST_LIST) { if (!LIST_ISEMPTY(&appctx->ctx.sess.bref.users)) LIST_DEL(&appctx->ctx.sess.bref.users);