mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-20 12:46:56 +00:00
BUG/MEDIUM: stick-tables: Fix race with peers when trashing oldest entries
It is the same that the one fixed in process_table_expire() (21447b1dd4
["BUG/MAJOR: stick-tables: fix race with peers in entry expiration"]). In
stktable_trash_oldest(), when the update lock is acquired, we must take care
to check again the ref_cnt because some peers may increment it (See commit
above for details).
This patch fixes a crash mentionned in 2552#issuecomment-2110532706. It must
be backported to 2.9.
This commit is contained in:
parent
51f9f6cfd4
commit
dfd938bad6
@ -264,6 +264,7 @@ int stktable_trash_oldest(struct stktable *t, int to_batch)
|
||||
int max_per_shard = (to_batch + CONFIG_HAP_TBL_BUCKETS - 1) / CONFIG_HAP_TBL_BUCKETS;
|
||||
int done_per_shard;
|
||||
int batched = 0;
|
||||
int updt_locked;
|
||||
int looped;
|
||||
int shard;
|
||||
|
||||
@ -272,6 +273,7 @@ int stktable_trash_oldest(struct stktable *t, int to_batch)
|
||||
while (batched < to_batch) {
|
||||
done_per_shard = 0;
|
||||
looped = 0;
|
||||
updt_locked = 0;
|
||||
|
||||
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->shards[shard].sh_lock);
|
||||
|
||||
@ -328,18 +330,35 @@ int stktable_trash_oldest(struct stktable *t, int to_batch)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if the entry is in the update list, we must be extremely careful
|
||||
* because peers can see it at any moment and start to use it. Peers
|
||||
* will take the table's updt_lock for reading when doing that, and
|
||||
* with that lock held, will grab a ref_cnt before releasing the
|
||||
* lock. So we must take this lock as well and check the ref_cnt.
|
||||
*/
|
||||
if (ts->upd.node.leaf_p) {
|
||||
if (!updt_locked) {
|
||||
updt_locked = 1;
|
||||
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->updt_lock);
|
||||
}
|
||||
/* now we're locked, new peers can't grab it anymore,
|
||||
* existing ones already have the ref_cnt.
|
||||
*/
|
||||
if (HA_ATOMIC_LOAD(&ts->ref_cnt))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* session expired, trash it */
|
||||
ebmb_delete(&ts->key);
|
||||
if (ts->upd.node.leaf_p) {
|
||||
HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->updt_lock);
|
||||
eb32_delete(&ts->upd);
|
||||
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
|
||||
}
|
||||
eb32_delete(&ts->upd);
|
||||
__stksess_free(t, ts);
|
||||
batched++;
|
||||
done_per_shard++;
|
||||
}
|
||||
|
||||
if (updt_locked)
|
||||
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->updt_lock);
|
||||
|
||||
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->shards[shard].sh_lock);
|
||||
|
||||
if (max_search <= 0)
|
||||
|
Loading…
Reference in New Issue
Block a user