diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 53f192d8bc976f..5f334584a3f709 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -839,36 +839,19 @@ void EEStartupHelper() #ifdef PROFILING_SUPPORTED // Initialize the profiling services. + // This must happen before Thread::HasStarted() that fires profiler notifications is called on the finalizer thread. hr = ProfilingAPIUtility::InitializeProfiling(); _ASSERTE(SUCCEEDED(hr)); IfFailGo(hr); #endif // PROFILING_SUPPORTED - InitializeExceptionHandling(); - - // - // Install our global exception filter - // - if (!InstallUnhandledExceptionFilter()) - { - IfFailGo(E_FAIL); - } - - // throws on error - SetupThread(); - -#ifdef DEBUGGING_SUPPORTED - // Notify debugger once the first thread is created to finish initialization. - if (g_pDebugInterface != NULL) - { - g_pDebugInterface->StartupPhase2(GetThread()); - } -#endif - - // This isn't done as part of InitializeGarbageCollector() above because - // debugger must be initialized before creating EE thread objects +#ifdef TARGET_WINDOWS + // Create the finalizer thread on windows earlier, as we will need to wait for + // the completion of its initialization part that initializes COM as that has to be done + // before the first Thread is attached. Thus we want to give the thread a bit more time. FinalizerThread::FinalizerThreadCreate(); +#endif InitPreStubManager(); @@ -882,8 +865,6 @@ void EEStartupHelper() // of the JIT helpers. InitJITHelpers1(); - SyncBlockCache::Attach(); - // Set up the sync block SyncBlockCache::Start(); @@ -898,6 +879,48 @@ void EEStartupHelper() IfFailGo(hr); + InitializeExceptionHandling(); + + // + // Install our global exception filter + // + if (!InstallUnhandledExceptionFilter()) + { + IfFailGo(E_FAIL); + } + +#ifdef TARGET_WINDOWS + // g_pGCHeap->Initialize() above could take nontrivial time, so by now the finalizer thread + // should have initialized FLS slot for thread cleanup notifications. + // And ensured that COM is initialized (must happen before allocating FLS slot). + // Make sure that this was done before we start creating Thread objects + // Ex: The call to SetupThread below will create and attach a Thread object. + // Event pipe might also do that. + FinalizerThread::WaitForFinalizerThreadStart(); +#endif + + // throws on error + _ASSERTE(GetThreadNULLOk() == NULL); + SetupThread(); + +#ifdef DEBUGGING_SUPPORTED + // Notify debugger once the first thread is created to finish initialization. + if (g_pDebugInterface != NULL) + { + g_pDebugInterface->StartupPhase2(GetThread()); + } +#endif + +#ifndef TARGET_WINDOWS + // This isn't done as part of InitializeGarbageCollector() above because + // debugger must be initialized before creating EE thread objects + FinalizerThread::FinalizerThreadCreate(); +#else + // On windows the finalizer thread is already partially created and is waiting + // right before doing HasStarted(). We will release it now. + FinalizerThread::EnableFinalization(); +#endif + #ifdef FEATURE_PERFTRACING // Finish setting up rest of EventPipe - specifically enable SampleProfiler if it was requested at startup. // SampleProfiler needs to cooperate with the GC which hasn't fully finished setting up in the first part of the @@ -957,12 +980,6 @@ void EEStartupHelper() g_MiniMetaDataBuffMaxSize, MEM_COMMIT, PAGE_READWRITE); #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS -#ifdef TARGET_WINDOWS - // By now finalizer thread should have initialized FLS slot for thread cleanup notifications. - // And ensured that COM is initialized (must happen before allocating FLS slot). - // Make sure that this was done. - FinalizerThread::WaitForFinalizerThreadStart(); -#endif g_fEEStarted = TRUE; g_EEStartupStatus = S_OK; hr = S_OK; @@ -1764,6 +1781,8 @@ void InitFlsSlot() // thread - thread to attach static void OsAttachThread(void* thread) { + _ASSERTE(g_flsIndex != FLS_OUT_OF_INDEXES); + if (t_flsState == FLS_STATE_INVOKED) { _ASSERTE_ALL_BUILDS(!"Attempt to execute managed code after the .NET runtime thread state has been destroyed."); diff --git a/src/coreclr/vm/finalizerthread.cpp b/src/coreclr/vm/finalizerthread.cpp index db45c4c0d8d9a1..4a445d9bc08754 100644 --- a/src/coreclr/vm/finalizerthread.cpp +++ b/src/coreclr/vm/finalizerthread.cpp @@ -392,6 +392,7 @@ DWORD WINAPI FinalizerThread::FinalizerThreadStart(void *args) // handshake with EE initialization, as now we can attach Thread objects to native threads. hEventFinalizerDone->Set(); + WaitForFinalizerEvent (hEventFinalizer); #endif s_FinalizerThreadOK = GetFinalizerThread()->HasStarted(); diff --git a/src/coreclr/vm/syncblk.cpp b/src/coreclr/vm/syncblk.cpp index 0d4e05a3bd4382..3839b0572b17c8 100644 --- a/src/coreclr/vm/syncblk.cpp +++ b/src/coreclr/vm/syncblk.cpp @@ -591,13 +591,6 @@ void SyncBlockCache::CleanupSyncBlocks() } EE_END_FINALLY; } -// create the sync block cache -/* static */ -void SyncBlockCache::Attach() -{ - LIMITED_METHOD_CONTRACT; -} - // create the sync block cache /* static */ void SyncBlockCache::Start()