Skip to content

Commit 41a0abd

Browse files
Copilotjkotas
andauthored
Serialize VSD DispatchCache unlinking with cache write lock (#128868)
Collectible ALC teardown can unlink `g_resolveCache` bucket entries concurrently with `Insert`/`PromoteChainEntry`, violating the cache’s single-writer assumption and allowing self-referential chain cycles that hang VSD resolution. This change restores writer serialization for unlink paths. Fixes #128859 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
1 parent ea17bc5 commit 41a0abd

2 files changed

Lines changed: 16 additions & 0 deletions

File tree

src/coreclr/vm/virtualcallstub.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,10 @@ void VirtualCallStubManager::ResetCache()
417417
// Go through each cache entry and if the cache element there is in
418418
// the cache entry heap of the manager being deleted, then we just
419419
// set the cache entry to empty.
420+
#ifdef CHAIN_LOOKUP
421+
// Serialize cache chain unlinking against concurrent insert/promote writers.
422+
CrstHolder lh(g_resolveCache->GetWriteLock());
423+
#endif
420424
DispatchCache::Iterator it(g_resolveCache);
421425
while (it.IsValid())
422426
{
@@ -681,6 +685,10 @@ VirtualCallStubManager::~VirtualCallStubManager()
681685
// Go through each cache entry and if the cache element there is in
682686
// the cache entry heap of the manager being deleted, then we just
683687
// set the cache entry to empty.
688+
#ifdef CHAIN_LOOKUP
689+
// Serialize cache chain unlinking against concurrent insert/promote writers.
690+
CrstHolder lh(g_resolveCache->GetWriteLock());
691+
#endif
684692
DispatchCache::Iterator it(g_resolveCache);
685693
while (it.IsValid())
686694
{

src/coreclr/vm/virtualcallstub.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,14 @@ class DispatchCache
13061306
cache[idx] = elem;
13071307
}
13081308

1309+
#ifdef CHAIN_LOOKUP
1310+
inline Crst *GetWriteLock()
1311+
{
1312+
LIMITED_METHOD_CONTRACT;
1313+
return &m_writeLock;
1314+
}
1315+
#endif
1316+
13091317
inline void ClearCacheEntry(size_t idx)
13101318
{
13111319
LIMITED_METHOD_CONTRACT;

0 commit comments

Comments
 (0)