From 9938fb9c7a5b62d9c78b9c60caba744b6191fd1d Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 23 May 2024 11:14:41 +0200 Subject: [PATCH] BUG/MEDIUM: stick-tables: Fix race with peers when killing a sticky session 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 | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/stick_table.c b/src/stick_table.c index 0d353e2e3..98afbe873 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -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; }