Native runtime keeps short weak handle for collectible AssemblyLoadContext
until the unload time when it gets converted to a strong one. A test
running with gc stress has recently hit a problem caused by the fact
that the weak handle is "short weak" and thus doesn't track
resurrection. Here is what happened:
* The test code has lost reference to the AssemblyLoadContext
* Finalizer was just invoked on that context due to that and so the weak
short handle was destroyed.
* Native runtime called AssemblyLoadContext.Resolve with the now dead
handle, the function tried to get the managed object and failed.
The fix is to change the handle type to long weak so that it doesn't get
destroyed before the finalization.
Commit migrated from https://github.com/dotnet/coreclr/commit/
65918165dbeb24861f27fc96f0ccf380b13097d3
throw new InvalidOperationException(SR.GetResourceString("AssemblyLoadContext_Constructor_CannotInstantiateWhileUnloading"));
}
- // If this is a collectible ALC, we are creating a weak handle otherwise we use a strong handle
- var thisHandle = GCHandle.Alloc(this, IsCollectible ? GCHandleType.Weak : GCHandleType.Normal);
+ // If this is a collectible ALC, we are creating a weak handle tracking resurrection otherwise we use a strong handle
+ var thisHandle = GCHandle.Alloc(this, IsCollectible ? GCHandleType.WeakTrackResurrection : GCHandleType.Normal);
var thisHandlePtr = GCHandle.ToIntPtr(thisHandle);
m_pNativeAssemblyLoadContext = InitializeAssemblyLoadContext(thisHandlePtr, fRepresentsTPALoadContext, isCollectible);
// CLRPrivBinderAssemblyLoadContext::ReleaseLoadContext is called.
OBJECTHANDLE handle = reinterpret_cast<OBJECTHANDLE>(m_ptrManagedAssemblyLoadContext);
OBJECTHANDLE strongHandle = reinterpret_cast<OBJECTHANDLE>(ptrManagedStrongAssemblyLoadContext);
- DestroyShortWeakHandle(handle);
+ DestroyLongWeakHandle(handle);
m_ptrManagedAssemblyLoadContext = reinterpret_cast<INT_PTR>(strongHandle);
_ASSERTE(m_pAssemblyLoaderAllocator != NULL);