]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: peers: make the soft-stop "dont_stop" state per peers section
authorFrederic Lecaille <flecaille@haproxy.com>
Wed, 21 Oct 2026 13:58:32 +0000 (15:58 +0200)
committerFrederic Lecaille <flecaille@haproxy.com>
Mon, 26 Oct 2026 15:30:43 +0000 (16:30 +0100)
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.

include/haproxy/peers-t.h
src/peers.c

index ab74ea44b6c0f8a213142da944ebfd1e5078eab2..4bff874bbd891fac06be2c3e669ac22278481745 100644 (file)
@@ -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 */
 };
 
index 64fdfdd9c9ccd989902d96674960d0e045847687..b59eb5725d24d729038df0d895cf4ecc035f4f73 100644 (file)
@@ -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);
                        }