util/IntrusiveHashSet: insert_check() returns the bucket head on success

The list head is a stable value that is guaranteed to be still valid
when insert_commit() gets called.

This fixes a linked list corruption bug in class StaticCache which
occurs when the cache item pointed to by the iterator gets evicted
between insert_check() and insert_commit().
This commit is contained in:
Max Kellermann 2023-07-21 13:34:02 +02:00 committed by Max Kellermann
parent 42d5b05f54
commit aeadae5399

View File

@ -227,7 +227,11 @@ public:
if (equal(key, i)) if (equal(key, i))
return {bucket.iterator_to(i), false}; return {bucket.iterator_to(i), false};
return {bucket.begin(), true}; /* bucket.end() is a pointer to the bucket's list
head, a stable value that is guaranteed to be still
valid when insert_commit() gets called
eventually */
return {bucket.end(), true};
} }
/** /**
@ -237,7 +241,10 @@ public:
*/ */
constexpr void insert_commit(bucket_iterator bucket, reference item) noexcept { constexpr void insert_commit(bucket_iterator bucket, reference item) noexcept {
++counter; ++counter;
GetBucket(item).insert(bucket, item);
/* using insert_after() so the new item gets inserted
at the front of the bucket list */
GetBucket(item).insert_after(bucket, item);
} }
/** /**