From: Frederic Lecaille Date: Wed, 21 Oct 2026 13:58:32 +0000 (+0200) Subject: BUG/MEDIUM: peers: make the soft-stop "dont_stop" state per peers section X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=a8953d84a21fd4d04ee53dadd5c9a2f9b5b33eaa;p=haproxy.git BUG/MEDIUM: peers: make the soft-stop "dont_stop" state per peers section Commit 608e23c49 ("MINOR: peers: Use a static variable to wait a resync on reload") replaced the PEERS_F_DONOTSTOP flag with a static variable in __process_stopping_peer_sync(), considering that it was only used in this function. But this function is called by the sync task of each peers section, so the variable is shared between all sections. With more than one peers section, upon soft-stop, only the first section to process the signal arms its resync timeout, requests the local reconnect and kills its sessions; the other ones see dont_stop already set and skip this. Then the first section which completes (or times out) decrements jobs and resets the variable, possibly allowing the old process to leave before the other sections have pushed their tables to the new process, and without releasing the table refcounts of the remaining sections. The variable is also accessed from multiple threads since each section's task may run on a different thread. Let's store this state in the peers section itself. This must be backported to 3.0. --- diff --git a/include/haproxy/peers-t.h b/include/haproxy/peers-t.h index ab74ea44b..4bff874bb 100644 --- a/include/haproxy/peers-t.h +++ b/include/haproxy/peers-t.h @@ -199,6 +199,7 @@ struct peers { int count; /* total of peers */ int nb_shards; /* Number of peer shards */ int disabled; /* peers proxy disabled if >0 */ + int dont_stop; /* blocks the process during soft-stop to push data to new process */ int applet_count[MAX_THREADS]; /* applet count per thread */ }; diff --git a/src/peers.c b/src/peers.c index 64fdfdd9c..b59eb5725 100644 --- a/src/peers.c +++ b/src/peers.c @@ -3838,7 +3838,6 @@ static void __process_stopping_peer_sync(struct task *task, struct peers *peers, { struct peer *peer; struct shared_table *st; - static int dont_stop = 0; /* For each peer */ for (peer = peers->remote; peer; peer = peer->next) { @@ -3853,7 +3852,7 @@ static void __process_stopping_peer_sync(struct task *task, struct peers *peers, */ peer->flags &= ~PEER_F_WAIT_SYNCTASK_ACK; - if ((state & TASK_WOKEN_SIGNAL) && !dont_stop) { + if ((state & TASK_WOKEN_SIGNAL) && !peers->dont_stop) { /* we're killing a connection, we must apply a random delay before * retrying otherwise the other end will do the same and we can loop * for a while. @@ -3870,10 +3869,10 @@ static void __process_stopping_peer_sync(struct task *task, struct peers *peers, /* We've just received the signal */ if (state & TASK_WOKEN_SIGNAL) { - if (!dont_stop) { + if (!peers->dont_stop) { /* add DO NOT STOP flag if not present */ _HA_ATOMIC_INC(&jobs); - dont_stop = 1; + peers->dont_stop = 1; /* Set resync timeout for the local peer and request a immediate reconnect */ peers->resync_timeout = tick_add(now_ms, MS_TO_TICKS(PEER_RESYNC_TIMEOUT)); @@ -3884,10 +3883,10 @@ static void __process_stopping_peer_sync(struct task *task, struct peers *peers, peer = peers->local; HA_SPIN_LOCK(PEER_LOCK, &peer->lock); if (peer->flags & PEER_F_LOCAL_TEACH_COMPLETE) { - if (dont_stop) { + if (peers->dont_stop) { /* resync of new process was complete, current process can die now */ _HA_ATOMIC_DEC(&jobs); - dont_stop = 0; + peers->dont_stop = 0; for (st = peer->tables; st ; st = st->next) HA_ATOMIC_DEC(&st->table->refcnt); } @@ -3917,17 +3916,17 @@ static void __process_stopping_peer_sync(struct task *task, struct peers *peers, } else { /* connect to the local peer if we must push a local sync */ - if (dont_stop) { + if (peers->dont_stop) { peer_session_create(peers, peer); } } } else { /* Other error cases */ - if (dont_stop) { + if (peers->dont_stop) { /* unable to resync new process, current process can die now */ _HA_ATOMIC_DEC(&jobs); - dont_stop = 0; + peers->dont_stop = 0; for (st = peer->tables; st ; st = st->next) HA_ATOMIC_DEC(&st->table->refcnt); }