From: Christopher Faulet Date: Thu, 12 Nov 2026 07:14:51 +0000 (+0100) Subject: BUG/MEDIUM: cache: fix "show cache" crash/skip with several caches X-Git-Url: https://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=171dff32dcbd3a6842055016ff3e3da0b1307b00;p=haproxy.git BUG/MEDIUM: cache: fix "show cache" crash/skip with several caches With "show cache" cli command, a crash could be experienced when several caches are configured. This happened when iterating on the second cache in the list. Indded the cache tree array was not reset when the dump of a cache was finished, leading to computing the cache tree index against the wrong cache tree and to lock the wrong cache tree. This is a regression introduced by the resumable CLI output. Fix it by clearing ctx->cache_tree when the dump of a cache finishes: the pointer must only be non-NULL while the dump is paused on the cache it belongs to. This patch must be backported to all supported versions. --- diff --git a/reg-tests/cache/multi_caches_show.vtc b/reg-tests/cache/multi_caches_show.vtc new file mode 100644 index 000000000..ee528ca8f --- /dev/null +++ b/reg-tests/cache/multi_caches_show.vtc @@ -0,0 +1,53 @@ +varnishtest "show cache must dump all the caches, not only the first one" + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp -hdr "Cache-Control: max-age=60" -body "x" +} -start + +haproxy h1 -conf { + global + stats socket /tmp/mc.sock + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe + bind "fd@${fe}" + http-request cache-use c1 + http-response cache-store c1 + http-response cache-store c2 + default_backend be + + backend be + server s ${s1_addr}:${s1_port} + + cache c1 + total-max-size 4 + + cache c2 + total-max-size 4 + + cache c3 + total-max-size 4 +} -start + +client c1 -connect ${h1_fe_sock} { + txreq -url "/a" + rxresp + expect resp.status == 200 +} -run + +# Without the fix, cli_io_handler_show_cache() computes the resume index of +# the second cache from the tree pointer left over by the first cache's dump: +# the index is garbage. Depending on the mmap order of the shctxs, the entries +# of the following caches are skipped, or their dump crashes the process. +haproxy h1 -cli { + send "show cache" + expect ~ "(?s)c1.*hash.*c2.*hash.*c3" +} diff --git a/src/cache.c b/src/cache.c index 8e9cc75e7..3e3a2119e 100644 --- a/src/cache.c +++ b/src/cache.c @@ -3816,6 +3816,9 @@ static int cli_io_handler_show_cache(struct appctx *appctx) } cache_rdunlock(cache_tree); } + + /* Reset the cache tree for the next cache */ + ctx->cache_tree = NULL; } free_trash_chunk(buf);