From 993c09438ba98cf0295d37a49aff1a20ba2efbda Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 10 Sep 2025 11:27:27 +0200 Subject: [PATCH] BUG/MEDIUM: stick-tables: don't loop on non-expirable entries The stick-table expiration of ref-counted entries was insufficiently addresse by commit 324f0a60ab ("BUG/MINOR: stick-tables: never leave used entries without expiration"), because now entries are just requeued where they were, so they're visited over and over for long sessions, causing process_table_expire() to loop, eating CPU and causing lock contention. Here we take care of refreshing their timeer when they are met, so that we don't meet them more than once per stick-table lifetime. It should address at least a part of the recent degradation that Felipe noticed in GH #3084. Since the fix above was marked for backporting to 3.2, this one should be backported there as well. --- src/stick_table.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/stick_table.c b/src/stick_table.c index cb70d16c2..5b5fdea90 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -988,8 +988,17 @@ struct task *process_table_expire(struct task *task, void *context, unsigned int */ eb32_delete(&ts->exp); - if (!tick_is_expired(ts->expire, now_ms) || HA_ATOMIC_LOAD(&ts->ref_cnt) != 0) { + if (HA_ATOMIC_LOAD(&ts->ref_cnt) != 0) { requeue: + /* we can't trash this entry yet because it's in use, + * so we must refresh it with the table's lifetime to + * postpone its expiration. + */ + if (tick_is_expired(ts->expire, now_ms)) + ts->expire = tick_add(now_ms, MS_TO_TICKS(t->expire)); + } + + if (!tick_is_expired(ts->expire, now_ms)) { if (!tick_isset(ts->expire)) continue;