From: Amaury Denoyelle Date: Tue, 21 Jul 2026 09:35:25 +0000 (+0200) Subject: BUG/MEDIUM: proxy: protect show backend against be deletion X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/doc/hash.html?a=commitdiff_plain;h=35f60950f95a69064bee9f7814d19a92aba80ba4;p=haproxy.git BUG/MEDIUM: proxy: protect show backend against be deletion Command "show backend" loops over the list of visible proxies to display information about all the backend instances. This command may yield in case of a long output, but this is not safe with introduction of dynamic backend deletion at runtime. Fixes this by using the watcher mechanism, similarly to what is implemented for stats dump. To support this, a new context dedicated to "show backend" has been defined. This must be backported up to 3.4. --- diff --git a/src/proxy.c b/src/proxy.c index 61457b49c..62b45b8c1 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -82,6 +82,12 @@ unsigned int error_snapshot_id = 0; /* global ID assigned to each error then unsigned int dynpx_next_id = 0; /* lowest ID assigned to dynamic proxies */ +/* CLI context used during "show backend" */ +struct show_be_ctx { + struct proxy *px; + struct watcher px_watch; /* watcher to automatically update px pointer on backend deletion */ +}; + /* CLI context used during "show servers {state|conn}" */ struct show_srv_ctx { struct proxy *px; /* current proxy to dump or NULL */ @@ -4609,20 +4615,23 @@ static int cli_io_handler_servers_state(struct appctx *appctx) */ static int cli_io_handler_show_backend(struct appctx *appctx) { + struct show_be_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx)); struct proxy *curproxy; chunk_reset(&trash); - if (!appctx->svcctx) { + if (!ctx->px) { chunk_printf(&trash, "# name\n"); if (applet_putchk(appctx, &trash) == -1) return 0; - appctx->svcctx = proxies_list; + watcher_init(&ctx->px_watch, &ctx->px, offsetof(struct proxy, watcher_list)); + /* This will automatically update ctx->px pointer. */ + watcher_attach(&ctx->px_watch, proxies_list); } - for (; appctx->svcctx != NULL; appctx->svcctx = curproxy->next) { - curproxy = appctx->svcctx; + for (; ctx->px; watcher_next(&ctx->px_watch, ctx->px->next)) { + curproxy = ctx->px; /* looking for non-internal backends only */ if ((curproxy->cap & (PR_CAP_BE|PR_CAP_INT)) != PR_CAP_BE)