You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I encountered a VM assertion failure while doing a run of Fuzzlyn with new changes from jakobbotsch/Fuzzlyn#23. Fuzzlyn uses AssemblyLoadContext to load generated assemblies from a client into its execution server and unloads the AssemblyLoadContext every ~100 iterations. With this new PR, Fuzzlyn now uses separate process pools for the base/diff programs, so each iteration is split in half, meaning that those unload events happen effectively twice as often. That seems like a possible explanation for why this surfaced.
Copilot Analysis:
Note
The following was generated with Copilot assistance.
Root cause: this is a CoreCLR lock-scope bug introduced by #128868.
VirtualCallStubManager::~VirtualCallStubManager() acquires CrstStubDispatchCache while unlinking entries. Because #ifdef does not create a C++ scope, the CrstHolder remains alive for the rest of the destructor. The destructor subsequently deletes executable loader heaps, which acquire CrstExecutableAllocatorLock . Both locks are level 0, producing the exact assertion:
Can't take level 0 lock CrstExecutableAllocatorLock
because you already holding level 0 lock CrstStubDispatchCache
The surgical runtime fix is to scope the cache lock around only the unlink loop:
{
#ifdef CHAIN_LOOKUP
CrstHolder lh(g_resolveCache->GetWriteLock());
#endif
DispatchCache::Iterator it(g_resolveCache);
while (it.IsValid())
{
while (it.IsValid() && cache_entry_rangeList.IsInRange((TADDR)it.Entry()))
{
it.UnlinkEntry();
}
it.Next();
}
} // Release CrstStubDispatchCache before deleting executable heaps.
Reproduction Steps
Found with: $ dotnet Fuzzlyn.dll --host "$env:CORE_ROOT\corerun.exe" --num-programs 10000 --interpreter-vs-jit
Description
I encountered a VM assertion failure while doing a run of Fuzzlyn with new changes from jakobbotsch/Fuzzlyn#23. Fuzzlyn uses AssemblyLoadContext to load generated assemblies from a client into its execution server and unloads the AssemblyLoadContext every ~100 iterations. With this new PR, Fuzzlyn now uses separate process pools for the base/diff programs, so each iteration is split in half, meaning that those unload events happen effectively twice as often. That seems like a possible explanation for why this surfaced.
Copilot Analysis:
Note
The following was generated with Copilot assistance.
Root cause: this is a CoreCLR lock-scope bug introduced by #128868.
VirtualCallStubManager::~VirtualCallStubManager() acquires CrstStubDispatchCache while unlinking entries. Because #ifdef does not create a C++ scope, the CrstHolder remains alive for the rest of the destructor. The destructor subsequently deletes executable loader heaps, which acquire CrstExecutableAllocatorLock . Both locks are level 0, producing the exact assertion:
Can't take level 0 lock CrstExecutableAllocatorLock
because you already holding level 0 lock CrstStubDispatchCache
The surgical runtime fix is to scope the cache lock around only the unlink loop:
{ #ifdef CHAIN_LOOKUP CrstHolder lh(g_resolveCache->GetWriteLock()); #endif DispatchCache::Iterator it(g_resolveCache); while (it.IsValid()) { while (it.IsValid() && cache_entry_rangeList.IsInRange((TADDR)it.Entry())) { it.UnlinkEntry(); } it.Next(); } } // Release CrstStubDispatchCache before deleting executable heaps.Reproduction Steps
Found with:
$ dotnet Fuzzlyn.dll --host "$env:CORE_ROOT\corerun.exe" --num-programs 10000 --interpreter-vs-jitExpected behavior
No assertion.
Actual behavior
Assert:
Regression?
No response
Known Workarounds
No response
Configuration
Revision:
Main: c4eee2bOS: Windows
Architecture: x64
Other information
No response