Skip to content

Commit 11e144a

Browse files
jbmscopybara-github
authored andcommitted
Fix data race when releasing weak pool reference held by cache
PiperOrigin-RevId: 805961624 Change-Id: Id86ba503a3f3b256363037be831201c0fbdd0f26
1 parent 5c29155 commit 11e144a

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

tensorstore/internal/cache/cache.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -557,16 +557,16 @@ PinnedCacheEntry<Cache> GetCacheEntryInternal(internal::Cache* cache,
557557
}
558558

559559
void StrongPtrTraitsCache::decrement_impl(CacheImpl* cache) noexcept {
560+
// Note: `pool_` must be accessed here because `cache` may have been
561+
// concurrently destroyed after calling `DecrementCacheReferenceCount` unless
562+
// `should_delete==true`.
563+
CachePoolImpl* pool = cache->pool_;
560564
auto decrement_result =
561565
DecrementCacheReferenceCount(cache, CacheImpl::kStrongReferenceIncrement);
562-
CachePoolImpl* pool = nullptr;
563-
if (decrement_result.should_release_cache_pool_weak_reference()) {
564-
pool = cache->pool_;
565-
}
566566
if (decrement_result.should_delete()) {
567-
DestroyCache(cache->pool_, cache);
567+
DestroyCache(pool, cache);
568568
}
569-
if (pool) {
569+
if (decrement_result.should_release_cache_pool_weak_reference() && pool) {
570570
ReleaseWeakReference(pool);
571571
}
572572
}

tensorstore/internal/cache/cache_test.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,9 @@ TEST(CacheTest, WeakRefOwnedByEntry) {
11131113
auto entry_b = GetCacheEntry(cache1, "b");
11141114
entry_a->weak_ref = entry_b->AcquireWeakReference();
11151115
}
1116-
{ auto entry_c = GetCacheEntry(cache2, "c"); }
1116+
{
1117+
auto entry_c = GetCacheEntry(cache2, "c");
1118+
}
11171119

11181120
EXPECT_THAT(log->entry_destroy_log, ElementsAre());
11191121
pool = {};
@@ -1127,4 +1129,29 @@ TEST(CacheTest, WeakRefOwnedByEntry) {
11271129
Pair("cache2", "c")));
11281130
}
11291131

1132+
TEST(CacheTest, ConcurrentReleaseStrongCachePoolEvict) {
1133+
CachePool::StrongPtr pool;
1134+
CachePtr<TestCache> cache1, cache2;
1135+
TestConcurrent(
1136+
kDefaultIterations,
1137+
/*initialize=*/
1138+
[&] {
1139+
CachePool::Limits limits;
1140+
limits.total_bytes_limit = 1;
1141+
pool = CachePool::Make(limits);
1142+
cache1 = GetTestCache(pool.get(), "x");
1143+
cache2 = GetTestCache(pool.get(), "y");
1144+
GetCacheEntry(cache1, "a");
1145+
},
1146+
/*finalize=*/
1147+
[&] {},
1148+
// Concurrent operations:
1149+
[&] { pool = {}; }, // release strong reference to pool
1150+
[&] { cache1 = {}; }, // release strong reference to cache1
1151+
[&] {
1152+
GetCacheEntry(cache2, "b");
1153+
} // create new cache entry in cache2, evicting only entry in cache1
1154+
);
1155+
}
1156+
11301157
} // namespace

0 commit comments

Comments
 (0)