Fix allocation of RuntimeTypeCache GC handle (#33243)
authorJan Vorlicek <janvorli@microsoft.com>
Thu, 5 Mar 2020 20:57:16 +0000 (21:57 +0100)
committerGitHub <noreply@github.com>
Thu, 5 Mar 2020 20:57:16 +0000 (21:57 +0100)
commit327801e8b838b97950cb8daaeef724acbe4e3c5f
treec035b2f9e6a09842b2aed5a691dd080462f3c823
parent362236a6abcaf28b508ac2042d83c1359c77c198
Fix allocation of RuntimeTypeCache GC handle (#33243)

When there is a race calling RuntimeType.InitializeCache, each of the
racing threads creates a new GC handle using
new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection);
This ends up calling RuntimeTypeHandle::GetGCHandle native method that
adds the allocated handle into the handle cleanup list of the
AssemblyLoaderAllocator specific for the runtime type.
All but the winning thread then call GCHandle.InternalFree on the just
allocated handle. That frees the handle, but leaves it on the cleanup
list of the loader allocator. The same handle can be later allocated for some
other purpose. When the AssemblyLoaderAllocator is being destroyed, all
the handles on the cleanup list are destroyed too. So it destroys also
the handle that was left on the cleanup list incorrectly. That can cause
all kinds of hard to diagnose issues, like the #32171.

This change fixes it by adding a FreeGCHandle method on the
RuntimeTypeHandle that besides freeing the handle also removes it from
the cleanup list of the related AssemblyLoadContext.
src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs
src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
src/coreclr/src/vm/ecalllist.h
src/coreclr/src/vm/loaderallocator.cpp
src/coreclr/src/vm/loaderallocator.hpp
src/coreclr/src/vm/runtimehandles.cpp
src/coreclr/src/vm/runtimehandles.h