-
Notifications
You must be signed in to change notification settings - Fork 5k
Move FLS init before EventPipeAdapter::FinishInitialize and the first SetupThread() #115546
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
Changes from all commits
0d014b6
b148eff
6642dcd
fdec3bd
4fc42cc
e119a35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we end up creating the finalizer thread too soon on non-Windows? For example, can the finalizer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If The comments inside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
These comments refer to the old profiler attach implementation. I am deleting them in #115680
Yes, look for "Attach" under https://github.com/dotnet/runtime/tree/main/src/tests/profiler. (The tests won't hit every subtle race condition though.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've moved the profiler initializtion earlier. If it needs to attach a Thread, then it would hit an assert in I was mostly wondering if we test scenarios beyond "profiler is not involved at all". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With default test set there are no failures, so based on that we could say profiler initializtion does not create/attach Thread objects - directly or indirectly, then it is all good. If the profiler tests you've pointed to run in default test set, it may be good enough. If we need to run some other leg - like outer loop, perhaps makes sense to do that. Maybe makes sense to do that regardless. |
||
// 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(); | ||
VSadov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#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."); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HasStarted
on the finalizer thread will send ThreadCreated notifications to the debugger. On non-Windows, are there going to be issues if this debugger notification on the finalizer thread is sent to debugger before this StartupPhase2 finishes?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SetupThread
also callsThreadCreated
and the EE initializing thread callsThreadCreated
beforeStartupPhase2
is called.Both
SetupThread
andHasStarted
will check forif (CORDebuggerAttached())
before sending the notification though.The functional part of
ThreadCreated
(apart from notifications) is to check if debugger wants threads to stop, which cannot happen if debugger is not yet officially attached.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there could be a race where finalizer thread checks if debugger is attached (sees that it is not) and then debugger asks threads to stop.
There is no such race for the thread that initializes the EE.