]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stick-tables: Fix race with peers when killing a sticky session
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 23 May 2024 09:14:41 +0000 (11:14 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 24 May 2024 09:52:11 +0000 (11:52 +0200)
When a sticky session is killed, we must be sure no other entity is still
referencing it. The session's ref_cnt must be 0. However, there is a race
with peers, as decribed in 21447b1dd4 ("BUG/MAJOR: stick-tables: fix race
with peers in entry expiration"). When the update lock is acquire, we must
recheck the ref_cnt value.

This patch is part of a debugging session about issue #2552. It must be
backported to 2.9.

src/stick_table.c

index 0d353e2e389a3a983fb6a107d08717fbecfcda2e..98afbe8736f2c8cb991f7fa478084f2a1abd221e 100644 (file)
@@ -141,17 +141,25 @@ void stksess_free(struct stktable *t, struct stksess *ts)
  */
 int __stksess_kill(struct stktable *t, struct stksess *ts)
 {
+       int updt_locked = 0;
+
        if (HA_ATOMIC_LOAD(&ts->ref_cnt))
                return 0;
 
-       eb32_delete(&ts->exp);
        if (ts->upd.node.leaf_p) {
+               updt_locked = 1;
                HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->updt_lock);
-               eb32_delete(&ts->upd);
-               HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
+               if (HA_ATOMIC_LOAD(&ts->ref_cnt))
+                       goto out_unlock;
        }
+       eb32_delete(&ts->exp);
+       eb32_delete(&ts->upd);
        ebmb_delete(&ts->key);
        __stksess_free(t, ts);
+
+  out_unlock:
+       if (updt_locked)
+               HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
        return 1;
 }