Skip to content

[9.0] Backport 115546 FLS initialization fix to 9. #116872

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 50 additions & 31 deletions src/coreclr/vm/ceemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -862,36 +862,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();

Expand All @@ -906,8 +889,6 @@ void EEStartupHelper()
InitJITHelpers1();
InitJITHelpers2();

SyncBlockCache::Attach();

// Set up the sync block
SyncBlockCache::Start();

Expand All @@ -922,6 +903,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
Expand Down Expand Up @@ -982,12 +1005,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;
Expand Down Expand Up @@ -1794,6 +1811,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.");
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/finalizerthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,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();
Expand Down
7 changes: 0 additions & 7 deletions src/coreclr/vm/syncblk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,13 +625,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()
Expand Down
Loading