]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: proxy: protect "show servers ..." against server deletion
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 21 Jul 2026 07:26:22 +0000 (09:26 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 21 Jul 2026 14:58:20 +0000 (16:58 +0200)
Command show servers conn/state loops over a server list to display
various information. This command may yield in case of a large output.
This can cause a crash if the server on which the command was paused is
deleted prior to restarting the command.

Fixes this by using the watcher mechanism, similar to what is already
implementing with stats dump.

This must be backported at least up to 3.0. For older releases, watcher
mechanism is not available, server refcount + SRV_F_DELETED flag must be
used instead.

src/proxy.c

index 8592e409a97960ca6b62451f3a11579c73edc836..7839989396f3138201089bd915280554a4f150df 100644 (file)
@@ -92,6 +92,8 @@ struct show_srv_ctx {
                SHOW_SRV_HEAD = 0,
                SHOW_SRV_LIST,
        } state;
+
+       struct watcher srv_watch; /* watcher to automatically update sv on server deletion */
 };
 
 /* proxy->options. For unsupported ones, pass 0 in the "cap" (PR_CAP_*) field.
@@ -4438,6 +4440,7 @@ static int cli_parse_show_servers(char **args, char *payload, struct appctx *app
        struct proxy *px;
 
        ctx->show_conn = *args[2] == 'c'; // "conn" vs "state"
+       watcher_init(&ctx->srv_watch, &ctx->sv, offsetof(struct server, watcher_list));
 
        /* check if a backend name has been provided */
        if (*args[3]) {
@@ -4489,9 +4492,9 @@ static int dump_servers_state(struct appctx *appctx)
        char *srvrecord;
 
        if (!ctx->sv)
-               ctx->sv = px->srv;
+               watcher_attach(&ctx->srv_watch, px->srv);
 
-       for (; ctx->sv != NULL; ctx->sv = srv->next) {
+       for (; ctx->sv; watcher_next(&ctx->srv_watch, ctx->sv->next)) {
                srv = ctx->sv;
 
                dump_server_addr(&srv->addr, srv_addr);