diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index eb3a2d8015ccd5..50b44b6ff6761f 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -3746,10 +3746,19 @@ void SaveManagedCommandLine(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR *argv) #endif } +static bool g_fIJWLoaded = false; + void Module::SetIsIJWFixedUp() { LIMITED_METHOD_CONTRACT; InterlockedOr((LONG*)&m_dwTransientFlags, IS_IJW_FIXED_UP); + g_fIJWLoaded = true; +} + +bool Module::HasAnyIJWBeenLoaded() +{ + LIMITED_METHOD_CONTRACT; + return g_fIJWLoaded; } #endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 5fee2e09f4bf79..0f9936e47f864c 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -1476,6 +1476,8 @@ class Module : public ModuleBase BOOL IsIJWFixedUp() { return m_dwTransientFlags & IS_IJW_FIXED_UP; } void SetIsIJWFixedUp(); + static bool HasAnyIJWBeenLoaded(); + BOOL IsBeingUnloaded() { return m_dwTransientFlags & IS_BEING_UNLOADED; } void SetBeingUnloaded(); void StartUnload(); diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 3df24664ff2df5..a75353ec28f990 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -1815,7 +1815,17 @@ static void OsAttachThread(void* thread) if (t_flsState == FLS_STATE_INVOKED) { - _ASSERTE_ALL_BUILDS(!"Attempt to execute managed code after the .NET runtime thread state has been destroyed."); + // Managed C++ may run managed code in DllMain (e.g. during DLL_PROCESS_DETACH to run global destructors). This is + // not supported and unreliable. Historically, it happened to work most of the time. For backward compatibility, + // suppress this assert in release builds if we have encountered any mixed mode binaries. + if (Module::HasAnyIJWBeenLoaded()) + { + _ASSERTE(!"Attempt to execute managed code after the .NET runtime thread state has been destroyed."); + } + else + { + _ASSERTE_ALL_BUILDS(!"Attempt to execute managed code after the .NET runtime thread state has been destroyed."); + } } t_flsState = FLS_STATE_ARMED;