]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: stick-table: release server_key on any stksess destruction
authorFrederic Lecaille <flecaille@haproxy.com>
Thu, 12 Nov 2026 17:05:08 +0000 (18:05 +0100)
committerFrederic Lecaille <flecaille@haproxy.com>
Thu, 12 Nov 2026 17:07:52 +0000 (18:07 +0100)
A stick-table storing server_key holds a reference on a dictionary entry
for each of its entries. This reference is released by stksess_free()
only, while expiry (process_table_expire()), eviction
(stktable_trash_oldest()) and explicit deletion (__stksess_kill(), also
used by "clear table") destroy the session through __stksess_free()
directly. The dictionary entry is then never freed: it stays in
server_key_dict with a refcount of 1 and no owner, and memory grows
linearly with the number of distinct values that went through the table.

Move the release into __stksess_free() so that every destruction path
releases it, and leave stksess_free() as a simple wrapper.

This must be backported to all stable versions.

src/stick_table.c

index dbfba8c70b462aa36d5c69809459459e5ea94837..af05bd4a00d273a17e1b00e0127db5553f4ea134 100644 (file)
@@ -90,6 +90,14 @@ struct stktable *stktable_find_by_name(const char *name)
  */
 void __stksess_free(struct stktable *t, struct stksess *ts)
 {
+       void *data;
+
+       data = stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY);
+       if (data) {
+               dict_entry_unref(&server_key_dict, stktable_data_cast(data, std_t_dict));
+               stktable_data_cast(data, std_t_dict) = NULL;
+       }
+
        HA_ATOMIC_DEC(&t->current);
        pool_free(t->pool, (void *)ts - round_ptr_size(t->data_size));
 }
@@ -101,14 +109,6 @@ void __stksess_free(struct stktable *t, struct stksess *ts)
  */
 void stksess_free(struct stktable *t, struct stksess *ts)
 {
-       void *data;
-
-       data = stktable_data_ptr(t, ts, STKTABLE_DT_SERVER_KEY);
-       if (data) {
-               dict_entry_unref(&server_key_dict, stktable_data_cast(data, std_t_dict));
-               stktable_data_cast(data, std_t_dict) = NULL;
-       }
-
        __stksess_free(t, ts);
 }