Skip to content

Commit 0bb8932

Browse files
committed
Sleep infinitely on secondary crashing threads
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 f5469fe commit 0bb8932

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)