FailFast stderr logging with stacktrace (dotnet/coreclr#11397)
authorViktor Hofer <viktor.hofer@microsoft.com>
Tue, 9 May 2017 00:41:06 +0000 (17:41 -0700)
committerJan Kotas <jkotas@microsoft.com>
Tue, 9 May 2017 00:41:06 +0000 (17:41 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/0c4a490a74c81e9735b0b7ef5b272add75e95ddf

src/coreclr/src/vm/eepolicy.cpp

index be5fa00..6bd389f 100644 (file)
@@ -1105,6 +1105,98 @@ void EEPolicy::HandleExitProcess(ShutdownCompleteAction sca)
     HandleExitProcessHelper(action, 0, sca);
 }
 
+StackWalkAction LogCallstackForLogCallback(
+    CrawlFrame       *pCF,      //
+    VOID*             pData     // Caller's private data
+)
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        SO_INTOLERANT;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
+
+    SmallStackSString *pWordAt = ((SmallStackSString*)pData);
+
+    MethodDesc *pMD = pCF->GetFunction();
+    _ASSERTE(pMD != NULL);
+
+    StackSString str;
+    str = *pWordAt;
+
+    TypeString::AppendMethodInternal(str, pMD, TypeString::FormatNamespace|TypeString::FormatFullInst|TypeString::FormatSignature); 
+    PrintToStdErrW(str.GetUnicode());
+    PrintToStdErrA("\n");
+
+    return SWA_CONTINUE;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// A worker to save managed stack trace.
+//
+// Arguments:
+//    reporter - EventReporter object for EventLog
+//
+// Return Value:
+//    None
+//
+inline void LogCallstackForLogWorker()
+{
+    Thread* pThread = GetThread();
+    _ASSERTE (pThread);
+
+    SmallStackSString WordAt;
+
+    if (!WordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT))
+    {
+        WordAt.Set(W("   at"));
+    }
+    else
+    {
+        WordAt.Insert(WordAt.Begin(), W("   "));
+    }
+    WordAt += W(" ");
+
+    pThread->StackWalkFrames(&LogCallstackForLogCallback, &WordAt, QUICKUNWIND | FUNCTIONSONLY);
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Generate an EventLog entry for unhandled exception.
+//
+// Arguments:
+//    pExceptionInfo - Exception information
+//
+// Return Value:
+//    None
+//
+inline void DoLogForFailFastException(LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo)
+{
+    WRAPPER_NO_CONTRACT;
+
+    Thread *pThread = GetThread();
+    EX_TRY
+    {
+        PrintToStdErrA("FailFast: ");
+        PrintToStdErrW((WCHAR*)pszMessage);
+        PrintToStdErrA("\n");
+
+        if (pThread)
+        {
+            PrintToStdErrA("\n");
+            LogCallstackForLogWorker();
+        }
+    }
+    EX_CATCH
+    {
+    }
+    EX_END_CATCH(SwallowAllExceptions)
+}
+
 //
 // Log an error to the event log if possible, then throw up a dialog box.
 //
@@ -1117,6 +1209,12 @@ void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage
 
     _ASSERTE(pExceptionInfo != NULL);
 
+    // Log FailFast exception to StdErr
+    if (exitCode == (UINT)COR_E_FAILFAST)
+    {
+        DoLogForFailFastException(pszMessage, pExceptionInfo);
+    }
+
     if(ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, FailFast))
     {
         // Fire an ETW FailFast event