From: Olivier Houchard Date: Thu, 3 Sep 2026 12:57:14 +0000 (+0200) Subject: BUG/MINOR: cli: Make sure two instances of _getsocks don't run X-Git-Tag: v3.5-dev7~44 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=f987d99fce4d44f9db5859b0fac309a6ace28bf5;p=haproxy.git BUG/MINOR: cli: Make sure two instances of _getsocks don't run It should never happen, but two instances of _getsocks could run at the same time, and cause a deadlock, so make sure that never happens by only allowing one at the same time. --- diff --git a/src/cli.c b/src/cli.c index d3569fdc1..b4ba0e365 100644 --- a/src/cli.c +++ b/src/cli.c @@ -2619,10 +2619,8 @@ static int _getsocks(char **args, char *payload, struct appctx *appctx, void *pr * a separate file descriptor table. */ nb_foreign = protocol_getsocks_foreign_fds(&foreign_rxs, &foreign_fds); - if (nb_foreign < 0) { - ha_warning("Failed to allocate memory to transfer other groups' sockets\n"); + if (nb_foreign < 0) goto out; - } /* * First, calculates the total number of FD, so that we can let diff --git a/src/protocol.c b/src/protocol.c index eb44f9802..c4c8fa800 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -182,6 +182,8 @@ void protocol_localize_rx_fds(void) HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); } +static uint getsocks_busy; + /* * Collect file descriptor from other thread groups, if they have their * own file descriptors table. @@ -193,6 +195,7 @@ int protocol_getsocks_foreign_fds(struct receiver ***orxs, int **ofds) struct receiver **rxs; int *fds; int nb, filled, done, i; + uint idle = 0; *orxs = NULL; *ofds = NULL; @@ -200,6 +203,14 @@ int protocol_getsocks_foreign_fds(struct receiver ***orxs, int **ofds) if (MAX_TGROUPS < 2 || !(global.tune.options & GTUNE_NO_TG_FD_SHARING) || global.nbtgroups < 2) return 0; + /* a concurrent collection would overwrite the per-receiver slots, and + * two of them blocking their groups' runner threads would deadlock. + */ + if (!HA_ATOMIC_CAS(&getsocks_busy, &idle, 1)) { + ha_warning("_getsocks: a collection is already in progress, giving up.\n"); + return -1; + } + /* first pass: count the candidates */ nb = 0; HA_SPIN_LOCK(PROTO_LOCK, &proto_lock); @@ -214,14 +225,18 @@ int protocol_getsocks_foreign_fds(struct receiver ***orxs, int **ofds) } HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock); - if (!nb) + if (!nb) { + HA_ATOMIC_STORE(&getsocks_busy, 0); return 0; + } rxs = calloc(nb, sizeof(*rxs)); fds = calloc(nb, sizeof(*fds)); if (!rxs || !fds) { free(rxs); free(fds); + HA_ATOMIC_STORE(&getsocks_busy, 0); + ha_warning("Failed to allocate memory to transfer other groups' sockets\n"); return -1; } @@ -282,6 +297,8 @@ int protocol_getsocks_foreign_fds(struct receiver ***orxs, int **ofds) done++; } + HA_ATOMIC_STORE(&getsocks_busy, 0); + if (!done) { free(rxs); free(fds);