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")
#include <shlwapi.h>
#ifdef TARGET_WINDOWS
-
-#include <process.h> // 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
{
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
#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
{
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;
}
}
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);
- }
- }
}
}
}
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
//