On Thu, Mar 31, 2022 at 11:56:13AM +0200, Willy Tarreau wrote: > > I've made some "session shutdown" tests. With simple configuration > > (attached) it is very easy to reproduce a situation when "shutdown session" > > works only for the first time. > > Indeed, thanks for this, I can as well reproduce it. With a bit of luck > I'll figure what's happening, hoping I won't unearth an ugly bug!
Now found and fixed. It's been bogus since we've split the list of streams to be per-thread in 2.4, patch attached if you need it. Thanks, Willy
>From c40c407268190e41d7d0238e3e2b7669147df9f7 Mon Sep 17 00:00:00 2001 From: Willy Tarreau <w...@1wt.eu> Date: Thu, 31 Mar 2022 14:49:45 +0200 Subject: BUG/MINOR: cli/stream: fix "shutdown session" to iterate over all threads The list of streams was modified in 2.4 to become per-thread with commit a698eb673 ("MINOR: streams: use one list per stream instead of a global one"). However the change applied to cli_parse_shutdown_session() is wrong, as it uses the nullity of the stream pointer to continue on next threads, but this one is not null once the list_for_each_entry() loop is finished, it points to the list's head again, so the loop doesn't check other threads, and no message is printed either to say that the stream was not found. Instead we should check if the stream is equal to the requested pointer since this is the condition to break out of the loop. Thus must be backported to 2.4. Thanks to Maciej Zdeb for reporting this. --- src/stream.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/stream.c b/src/stream.c index 8acce8075..fd8dada12 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3750,16 +3750,16 @@ static int cli_parse_shutdown_session(char **args, char *payload, struct appctx if (!cli_has_level(appctx, ACCESS_LVL_ADMIN)) return 1; - if (!*args[2]) - return cli_err(appctx, "Session pointer expected (use 'show sess').\n"); - ptr = (void *)strtoul(args[2], NULL, 0); + if (!ptr) + return cli_err(appctx, "Session pointer expected (use 'show sess').\n"); + strm = NULL; thread_isolate(); /* first, look for the requested stream in the stream table */ - for (thr = 0; !strm && thr < global.nbthread; thr++) { + for (thr = 0; strm != ptr && thr < global.nbthread; thr++) { list_for_each_entry(strm, &ha_thread_ctx[thr].streams, list) { if (strm == ptr) { stream_shutdown(strm, SF_ERR_KILLED); @@ -3771,7 +3771,7 @@ static int cli_parse_shutdown_session(char **args, char *payload, struct appctx thread_release(); /* do we have the stream ? */ - if (!strm) + if (strm != ptr) return cli_err(appctx, "No such session (use 'show sess').\n"); return 1; -- 2.35.1