Skip to content

Commit 5b8d9eb

Browse files
authored
Sleep infinitely on secondary crashing threads (#72618)
Sleeping infinitely instead of continuing should be better for crash reporting reliability. Also, change the crashing thread detection to use thread ID instead of Thread*. It is fixing bogus "Fatal error while logging another fatal error." message when the crash occurs without Thread* being setup.
1 parent 0b1c61e commit 5b8d9eb

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

src/coreclr/vm/eepolicy.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -325,25 +325,31 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, LPCWSTR errorSource
325325
{
326326
WRAPPER_NO_CONTRACT;
327327

328-
static Thread *const FatalErrorNotSeenYet = nullptr;
329-
static Thread *const FatalErrorLoggingFinished = reinterpret_cast<Thread *>(1);
328+
static size_t s_pCrashingThreadID;
330329

331-
static Thread *volatile s_pCrashingThread = FatalErrorNotSeenYet;
330+
size_t currentThreadID;
331+
#ifndef TARGET_UNIX
332+
currentThreadID = GetCurrentThreadId();
333+
#else
334+
currentThreadID = PAL_GetCurrentOSThreadId();
335+
#endif
332336

333-
Thread *pThread = GetThreadNULLOk();
334-
Thread *pPreviousThread = InterlockedCompareExchangeT<Thread *>(&s_pCrashingThread, pThread, FatalErrorNotSeenYet);
337+
size_t previousThreadID = InterlockedCompareExchangeT<size_t>(&s_pCrashingThreadID, currentThreadID, 0);
335338

336-
if (pPreviousThread == pThread)
337-
{
338-
PrintToStdErrA("Fatal error while logging another fatal error.\n");
339-
return;
340-
}
341-
else if (pPreviousThread != nullptr)
339+
// Let the first crashing thread take care of the reporting.
340+
if (previousThreadID != 0)
342341
{
343-
GCX_PREEMP(); // Avoid blocking other threads that may be trying to suspend the runtime
344-
while (s_pCrashingThread != FatalErrorLoggingFinished)
342+
if (previousThreadID == currentThreadID)
343+
{
344+
PrintToStdErrA("Fatal error while logging another fatal error.\n");
345+
}
346+
else
345347
{
346-
ClrSleepEx(50, /*bAlertable*/ FALSE);
348+
// Switch to preemptive mode to avoid blocking the crashing thread. It may try to suspend the runtime
349+
// for GC during the stacktrace reporting.
350+
GCX_PREEMP();
351+
352+
ClrSleepEx(INFINITE, /*bAlertable*/ FALSE);
347353
}
348354
return;
349355
}
@@ -379,9 +385,10 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, LPCWSTR errorSource
379385

380386
PrintToStdErrA("\n");
381387

388+
Thread* pThread = GetThreadNULLOk();
382389
if (pThread && errorSource == NULL)
383390
{
384-
LogCallstackForLogWorker(GetThread());
391+
LogCallstackForLogWorker(pThread);
385392

386393
if (argExceptionString != NULL) {
387394
PrintToStdErrW(argExceptionString);
@@ -392,8 +399,6 @@ void LogInfoForFatalError(UINT exitCode, LPCWSTR pszMessage, LPCWSTR errorSource
392399
{
393400
}
394401
EX_END_CATCH(SwallowAllExceptions)
395-
396-
InterlockedCompareExchangeT<Thread *>(&s_pCrashingThread, FatalErrorLoggingFinished, pThread);
397402
}
398403

399404
//This starts FALSE and then converts to true if HandleFatalError has ever been called by a GC thread

0 commit comments

Comments
 (0)