diff --git a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt index 67cbf59fe9472e..049622fbac0501 100644 --- a/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt +++ b/src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt @@ -10,8 +10,6 @@ if (CLR_CMAKE_HOST_WIN32) list(APPEND CLR_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/coreclr.def) - add_linker_flag("/ENTRY:CoreDllMain") - # Incremental linking results in the linker inserting extra padding and routing function calls via thunks that can break the # invariants (e.g. size of region between Jit_PatchedCodeLast-Jit_PatchCodeStart needs to fit in a page). add_linker_flag("/INCREMENTAL:NO") diff --git a/src/coreclr/src/dlls/mscoree/mscoree.cpp b/src/coreclr/src/dlls/mscoree/mscoree.cpp index f9e1e3d89ef68c..e32041c647e4ad 100644 --- a/src/coreclr/src/dlls/mscoree/mscoree.cpp +++ b/src/coreclr/src/dlls/mscoree/mscoree.cpp @@ -34,65 +34,9 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. #include #ifdef TARGET_WINDOWS - -#include // for __security_init_cookie() - -extern "C" BOOL WINAPI _CRT_INIT(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved); extern "C" BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved); - -// For the CoreClr, this is the real DLL entrypoint. We make ourselves the first entrypoint as -// we need to capture coreclr's hInstance before the C runtime initializes. This function -// will capture hInstance, let the C runtime initialize and then invoke the "classic" -// DllMain that initializes everything else. -extern "C" BOOL WINAPI CoreDllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) -{ - STATIC_CONTRACT_NOTHROW; - - BOOL result; - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - // Make sure the /GS security cookie is initialized before we call anything else. - // BinScope detects the call to __security_init_cookie in its "Has Non-GS-friendly - // Initialization" check and makes it pass. - __security_init_cookie(); - - // It's critical that we initialize g_hmodCoreCLR before the CRT initializes. - // We have a lot of global ctors that will break if we let the CRT initialize without - // this step having been done. - - g_hmodCoreCLR = (HINSTANCE)hInstance; - - if (!(result = _CRT_INIT(hInstance, dwReason, lpReserved))) - { - // CRT_INIT may fail to initialize the CRT heap. Make sure we don't continue - // down a path that would trigger an AV and tear down the host process - break; - } - result = DllMain(hInstance, dwReason, lpReserved); - break; - - case DLL_THREAD_ATTACH: - _CRT_INIT(hInstance, dwReason, lpReserved); - result = DllMain(hInstance, dwReason, lpReserved); - break; - - case DLL_PROCESS_DETACH: // intentional fallthru - case DLL_THREAD_DETACH: - result = DllMain(hInstance, dwReason, lpReserved); - _CRT_INIT(hInstance, dwReason, lpReserved); - break; - - default: - result = FALSE; // it'd be an OS bug if we got here - not much we can do. - break; - } - return result; -} - #endif // TARGET_WINDOWS - extern "C" #ifdef TARGET_UNIX DLLEXPORT // For Win32 PAL LoadLibrary emulation @@ -101,42 +45,7 @@ BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) { STATIC_CONTRACT_NOTHROW; - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { -#ifndef TARGET_WINDOWS - g_hmodCoreCLR = (HINSTANCE)hInstance; -#endif - - // Save the module handle. - g_hThisInst = (HINSTANCE)hInstance; - - // Prevent buffer-overruns - // If buffer is overrun, it is possible the saved callback has been trashed. - // The callback is unsafe. - //SetBufferOverrunHandler(); - if (!EEDllMain((HINSTANCE)hInstance, dwReason, lpReserved)) - { - return FALSE; - } - } - break; - - case DLL_PROCESS_DETACH: - { - EEDllMain((HINSTANCE)hInstance, dwReason, lpReserved); - } - break; - - case DLL_THREAD_DETACH: - { - EEDllMain((HINSTANCE)hInstance, dwReason, lpReserved); - } - break; - } - - return TRUE; + return EEDllMain((HINSTANCE)hInstance, dwReason, lpReserved); } #endif // CROSSGEN_COMPILE diff --git a/src/coreclr/src/vm/ceemain.cpp b/src/coreclr/src/vm/ceemain.cpp index 3526d9f8c776d3..c729cd66d0d3a4 100644 --- a/src/coreclr/src/vm/ceemain.cpp +++ b/src/coreclr/src/vm/ceemain.cpp @@ -635,6 +635,15 @@ void EEStartupHelper() #ifndef CROSSGEN_COMPILE + // We cache the SystemInfo for anyone to use throughout the life of the EE. + GetSystemInfo(&g_SystemInfo); + + // Set callbacks so that LoadStringRC knows which language our + // threads are in so that it can return the proper localized string. + // TODO: This shouldn't rely on the LCID (id), but only the name + SetResourceCultureCallbacks(GetThreadUICultureNames, + GetThreadUICultureId); + #ifndef TARGET_UNIX ::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/); #endif @@ -1820,16 +1829,9 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. { case DLL_PROCESS_ATTACH: { - // We cache the SystemInfo for anyone to use throughout the - // life of the DLL. - GetSystemInfo(&g_SystemInfo); - - // Set callbacks so that LoadStringRC knows which language our - // threads are in so that it can return the proper localized string. - // TODO: This shouldn't rely on the LCID (id), but only the name - SetResourceCultureCallbacks(GetThreadUICultureNames, - GetThreadUICultureId); - + g_hmodCoreCLR = pParam->hInst; + // Save the module handle. + g_hThisInst = pParam->hInst; break; } @@ -1859,35 +1861,6 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. } break; } - - case DLL_THREAD_DETACH: - { - // Don't destroy threads here if we're in shutdown (shutdown will - // clean up for us instead). - - Thread* thread = GetThread(); - if (thread) - { -#ifdef FEATURE_COMINTEROP - // reset the CoInitialize state - // so we don't call CoUninitialize during thread detach - thread->ResetCoInitialized(); -#endif // FEATURE_COMINTEROP - // For case where thread calls ExitThread directly, we need to reset the - // frame pointer. Otherwise stackwalk would AV. We need to do it in cooperative mode. - // We need to set m_GCOnTransitionsOK so this thread won't trigger GC when toggle GC mode - if (thread->m_pFrame != FRAME_TOP) - { -#ifdef _DEBUG - thread->m_GCOnTransitionsOK = FALSE; -#endif - GCX_COOP_NO_DTOR(); - thread->m_pFrame = FRAME_TOP; - GCX_COOP_NO_DTOR_END(); - } - thread->DetachThread(TRUE); - } - } } } @@ -1896,12 +1869,46 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. } PAL_ENDTRY; - if (dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH) + return TRUE; +} + +struct TlsDestructionMonitor +{ + ~TlsDestructionMonitor() { + // Don't destroy threads here if we're in shutdown (shutdown will + // clean up for us instead). + + Thread* thread = GetThread(); + if (thread) + { +#ifdef FEATURE_COMINTEROP + // reset the CoInitialize state + // so we don't call CoUninitialize during thread detach + thread->ResetCoInitialized(); +#endif // FEATURE_COMINTEROP + // For case where thread calls ExitThread directly, we need to reset the + // frame pointer. Otherwise stackwalk would AV. We need to do it in cooperative mode. + // We need to set m_GCOnTransitionsOK so this thread won't trigger GC when toggle GC mode + if (thread->m_pFrame != FRAME_TOP) + { +#ifdef _DEBUG + thread->m_GCOnTransitionsOK = FALSE; +#endif + GCX_COOP_NO_DTOR(); + thread->m_pFrame = FRAME_TOP; + GCX_COOP_NO_DTOR_END(); + } + thread->DetachThread(TRUE); + } + ThreadDetaching(); } - return TRUE; -} +}; + +// This thread local object is used to detect thread shutdown. Its destructor +// is called when a thread is being shut down. +thread_local TlsDestructionMonitor tls_destructionMonitor; #ifdef DEBUGGING_SUPPORTED //