]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stick-tables: don't loop on non-expirable entries
authorWilly Tarreau <w@1wt.eu>
Wed, 10 Sep 2025 09:27:27 +0000 (11:27 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 10 Sep 2025 09:27:27 +0000 (11:27 +0200)
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

index cb70d16c2c562f32bec353774da0e57446e62ea6..5b5fdea90cea1af582c7efb224cf8d206d3e22bb 100644 (file)
@@ -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;