Skip to content

Commit 56cb0eb

Browse files
Correctly lock around iterating the AvailableParamTypes hashtable when adding fields/classes via ApplyMetadata (#118608)
This does not eliminate all possible race conditions here, if a type is in progress loading when the metadata is updated, then there is still a race, but this should narrow the possible races in this space. Additionally, this should address the debug asserts which have been hit in this space. Fixes #115318
1 parent 60fc4db commit 56cb0eb

File tree

4 files changed

+15
-4
lines changed

4 files changed

+15
-4
lines changed

src/coreclr/vm/class.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ HRESULT EEClass::AddField(MethodTable* pMT, mdFieldDef fieldDef, FieldDesc** ppN
391391
LOG((LF_ENC, LL_INFO100, "EEClass::AddField Checking: %s mod:%p\n", pMod->GetDebugName(), pMod));
392392

393393
EETypeHashTable* paramTypes = pMod->GetAvailableParamTypes();
394+
CrstHolder ch(pMod->GetClassLoader()->GetAvailableTypesLock());
395+
394396
EETypeHashTable::Iterator it(paramTypes);
395397
EETypeHashEntry* pEntry;
396398
while (paramTypes->FindNext(&it, &pEntry))
@@ -587,6 +589,8 @@ HRESULT EEClass::AddMethod(MethodTable* pMT, mdMethodDef methodDef, MethodDesc**
587589
LOG((LF_ENC, LL_INFO100, "EEClass::AddMethod Checking: %s mod:%p\n", pMod->GetDebugName(), pMod));
588590

589591
EETypeHashTable* paramTypes = pMod->GetAvailableParamTypes();
592+
CrstHolder ch(pMod->GetClassLoader()->GetAvailableTypesLock());
593+
590594
EETypeHashTable::Iterator it(paramTypes);
591595
EETypeHashEntry* pEntry;
592596
while (paramTypes->FindNext(&it, &pEntry))

src/coreclr/vm/clsload.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1735,7 +1735,7 @@ VOID ClassLoader::Init(AllocMemTracker *pamTracker)
17351735
// This lock is taken within the classloader whenever we have to insert a new param. type into the table.
17361736
m_AvailableTypesLock.Init(
17371737
CrstAvailableParamTypes,
1738-
CRST_DEBUGGER_THREAD);
1738+
CrstFlags(CRST_DEBUGGER_THREAD | CRST_GC_NOTRIGGER_WHEN_TAKEN | CRST_UNSAFE_ANYMODE));
17391739

17401740
#ifdef _DEBUG
17411741
CorTypeInfo::CheckConsistency();

src/coreclr/vm/clsload.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,13 @@ class ClassLoader
533533

534534

535535
public:
536+
537+
CrstBase *GetAvailableTypesLock()
538+
{
539+
LIMITED_METHOD_CONTRACT;
540+
return &m_AvailableTypesLock;
541+
}
542+
536543
//#LoaderModule
537544
// LoaderModule determines in which module an item gets placed.
538545
// For everything except parameterized types and methods the choice is easy.

src/coreclr/vm/excep.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10824,7 +10824,7 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr)
1082410824
CONTRACTL
1082510825
{
1082610826
THROWS;
10827-
DISABLED(GC_NOTRIGGER); // Must sanitize first pass handling to enable this
10827+
GC_NOTRIGGER;
1082810828
MODE_ANY;
1082910829
}
1083010830
CONTRACTL_END;
@@ -10837,7 +10837,7 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr)
1083710837
// !
1083810838
// ! COMPlusThrowHR(hr, kGetErrorInfo)
1083910839

10840-
RealCOMPlusThrowHR(hr, (IErrorInfo*)NULL);
10840+
EX_THROW(EEMessageException, (hr));
1084110841
}
1084210842

1084310843
VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, tagGetErrorInfo)
@@ -10883,7 +10883,7 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, UINT resID, LPCWSTR wszArg
1088310883
CONTRACTL
1088410884
{
1088510885
THROWS;
10886-
DISABLED(GC_NOTRIGGER); // Must sanitize first pass handling to enable this
10886+
GC_NOTRIGGER;
1088710887
MODE_ANY;
1088810888
}
1088910889
CONTRACTL_END;

0 commit comments

Comments
 (0)