From 35e4aad602ee3c28330e94746cfd4e0d4569b66f Mon Sep 17 00:00:00 2001 From: Alexey Zakharov Date: Sat, 25 May 2024 14:24:48 +0200 Subject: [PATCH] =?UTF-8?q?=EF=BB=BFEnsure=20LoaderAllocator=20can't=20be?= =?UTF-8?q?=20collected=20while=20we=20clean=20handles=20on=20collectible?= =?UTF-8?q?=20LoaderAllocators=20(#99998)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/coreclr/vm/loaderallocator.cpp | 4 +--- src/coreclr/vm/threadstatics.cpp | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 4f625e592e8d9..dad12b8aa781f 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -964,13 +964,11 @@ void LoaderAllocator::SetHandleValue(LOADERHANDLE handle, OBJECTREF value) { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_COOPERATIVE; PRECONDITION(handle != NULL); } CONTRACTL_END; - GCX_COOP(); - GCPROTECT_BEGIN(value); // If the slot value does have the low bit set, then it is a simple pointer to the value diff --git a/src/coreclr/vm/threadstatics.cpp b/src/coreclr/vm/threadstatics.cpp index 74d2eb08a3dc8..aa9408a7791a6 100644 --- a/src/coreclr/vm/threadstatics.cpp +++ b/src/coreclr/vm/threadstatics.cpp @@ -52,13 +52,22 @@ void ThreadLocalBlock::FreeTLM(SIZE_T i, BOOL isThreadShuttingdown) ThreadLocalModule::CollectibleDynamicEntry *entry = (ThreadLocalModule::CollectibleDynamicEntry*)pThreadLocalModule->m_pDynamicClassTable[k].m_pDynamicEntry; PTR_LoaderAllocator pLoaderAllocator = entry->m_pLoaderAllocator; - if (entry->m_hGCStatics != 0) - { - pLoaderAllocator->FreeHandle(entry->m_hGCStatics); - } - if (entry->m_hNonGCStatics != 0) + // LoaderAllocator may be collected when the thread is shutting down. + // We enter coop mode to ensure that we get a valid value of the exposed object and + // can safely clean up handles if it is not yet collected. + GCX_COOP(); + + LOADERALLOCATORREF loaderAllocator = pLoaderAllocator->GetExposedObject(); + if (loaderAllocator != NULL) { - pLoaderAllocator->FreeHandle(entry->m_hNonGCStatics); + if (entry->m_hGCStatics != 0) + { + pLoaderAllocator->FreeHandle(entry->m_hGCStatics); + } + if (entry->m_hNonGCStatics != 0) + { + pLoaderAllocator->FreeHandle(entry->m_hNonGCStatics); + } } } delete pThreadLocalModule->m_pDynamicClassTable[k].m_pDynamicEntry;