BUG/MINOR: peers: Possible unexpected peer seesion reset after collisions.
authorFrédéric Lécaille <flecaille@haproxy.com>
Wed, 14 Oct 2020 09:50:26 +0000 (11:50 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 19 Oct 2020 07:57:13 +0000 (09:57 +0200)
During a peers session collision (two peer sessions opened on both side) we must
mark the peer the session of which will be shutdown as alive, if not ->reconnect
timer will be set with a wrong value if the synchro task expires after the peer
has been reconnected. This possibly leads to unexpected deconnections during handshakes.
Furthermore, this patch cancels any heartbeat tranmimission when a reconnection
is prepared.

(cherry picked from commit 6e1a9c57c938360e95f445e800f0d22782bb6c22)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/peers.c

index 295798e..fb7f80f 100644 (file)
@@ -796,8 +796,6 @@ void __peer_session_deinit(struct peer *peer)
        /* reset teaching and learning flags to 0 */
        peer->flags &= PEER_TEACH_RESET;
        peer->flags &= PEER_LEARN_RESET;
-       /* set this peer as dead from heartbeat point of view */
-       peer->flags &= ~PEER_F_ALIVE;
        task_wakeup(peers->sync_task, TASK_WOKEN_MSG);
 }
 
@@ -817,6 +815,7 @@ static void peer_session_release(struct appctx *appctx)
                HA_SPIN_LOCK(PEER_LOCK, &peer->lock);
                if (peer->appctx == appctx)
                        __peer_session_deinit(peer);
+               peer->flags &= ~PEER_F_ALIVE;
                HA_SPIN_UNLOCK(PEER_LOCK, &peer->lock);
        }
 }
@@ -2125,6 +2124,7 @@ static inline void init_accepted_peer(struct peer *peer, struct peers *peers)
 {
        struct shared_table *st;
 
+       peer->heartbeat = tick_add(now_ms, MS_TO_TICKS(PEER_HEARTBEAT_TIMEOUT));
        /* Register status code */
        peer->statuscode = PEER_SESS_SC_SUCCESSCODE;
 
@@ -2170,6 +2170,7 @@ static inline void init_connected_peer(struct peer *peer, struct peers *peers)
 {
        struct shared_table *st;
 
+       peer->heartbeat = tick_add(now_ms, MS_TO_TICKS(PEER_HEARTBEAT_TIMEOUT));
        /* Init cursors */
        for (st = peer->tables; st ; st = st->next) {
                st->last_get = st->last_acked = 0;
@@ -2275,6 +2276,7 @@ switchstate:
                                         */
                                        curpeer->reconnect = tick_add(now_ms, MS_TO_TICKS(50 + ha_random() % 2000));
                                        peer_session_forceshutdown(curpeer);
+                                       curpeer->heartbeat = TICK_ETERNITY;
                                }
                                if (maj_ver != (unsigned int)-1 && min_ver != (unsigned int)-1) {
                                        if (min_ver == PEER_DWNGRD_MINOR_VER) {
@@ -2285,6 +2287,7 @@ switchstate:
                                        }
                                }
                                curpeer->appctx = appctx;
+                               curpeer->flags |= PEER_F_ALIVE;
                                appctx->ctx.peers.ptr = curpeer;
                                appctx->st0 = PEER_SESS_ST_SENDSUCCESS;
                                _HA_ATOMIC_ADD(&active_peers, 1);
@@ -2546,7 +2549,7 @@ static struct appctx *peer_session_create(struct peers *peers, struct peer *peer
        struct stream *s;
 
        peer->reconnect = tick_add(now_ms, MS_TO_TICKS(PEER_RECONNECT_TIMEOUT));
-       peer->heartbeat = tick_add(now_ms, MS_TO_TICKS(PEER_HEARTBEAT_TIMEOUT));
+       peer->heartbeat = TICK_ETERNITY;
        peer->statuscode = PEER_SESS_SC_CONNECTCODE;
        s = NULL;
 
@@ -2727,6 +2730,7 @@ static struct task *process_peer_sync(struct task * task, void *context, unsigne
                                                                }
                                                                else  {
                                                                        ps->reconnect = tick_add(now_ms, MS_TO_TICKS(50 + ha_random() % 2000));
+                                                                       ps->heartbeat = TICK_ETERNITY;
                                                                        peer_session_forceshutdown(ps);
                                                                        ps->no_hbt++;
                                                                }