From aeadae53998b442f97a7027e6750c7977851bea3 Mon Sep 17 00:00:00 2001 From: Max Kellermann <mk@cm4all.com> Date: Fri, 21 Jul 2023 13:34:02 +0200 Subject: [PATCH] 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(). --- src/util/IntrusiveHashSet.hxx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/util/IntrusiveHashSet.hxx b/src/util/IntrusiveHashSet.hxx index 0cfd63635..01b86329e 100644 --- a/src/util/IntrusiveHashSet.hxx +++ b/src/util/IntrusiveHashSet.hxx @@ -227,7 +227,11 @@ public: if (equal(key, i)) 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 { ++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); } /**