From 7b6efe8351bb4b990e0582bc56e1e816ad3add9a Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Fri, 9 Mar 2018 16:41:03 -0800 Subject: [PATCH 01/12] Add FailFast error log to Windows Event Log --- src/vm/eepolicy.cpp | 7 ++++++- src/vm/eventreporter.cpp | 33 ++++++++++++++++++++++++++++----- src/vm/eventreporter.h | 2 ++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/vm/eepolicy.cpp b/src/vm/eepolicy.cpp index bdfe0fbf671e..d300276909a4 100644 --- a/src/vm/eepolicy.cpp +++ b/src/vm/eepolicy.cpp @@ -1262,7 +1262,7 @@ void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage else if (exitCode == (UINT)COR_E_CODECONTRACTFAILED) failureType = EventReporter::ERT_CodeContractFailed; EventReporter reporter(failureType); - + StackSString s(argExceptionString); if ((exitCode == (UINT)COR_E_FAILFAST) || (exitCode == (UINT)COR_E_CODECONTRACTFAILED) || (exitCode == (UINT)CLR_E_GC_OOM)) { @@ -1271,6 +1271,11 @@ void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage reporter.AddDescription((WCHAR*)pszMessage); } + if (argExceptionString) + { + reporter.AddFailFastStackTrace(s); + } + if (exitCode != (UINT)CLR_E_GC_OOM) LogCallstackForEventReporter(reporter); } diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index c73af36b5539..aa4a13abc351 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -343,6 +343,34 @@ void EventReporter::AddStackTrace(SString& s) } } +//--------------------------------------------------------------------------------------- +// +// Add the stack trace of exception passed to managed FailFast call (Environment.FailFast()) to Event Log +// +// Arguments: +// s - String representation of the stack trace of argument exception +// +// Return Value: +// None. +// +void EventReporter::AddFailFastStackTrace(SString& s) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + SO_INTOLERANT; + MODE_ANY; + } + CONTRACTL_END; + + _ASSERTE(m_eventType == ERT_ManagedFailFast); + + m_Description.Append(W("Exception stack:\n")); + m_Description.Append(s); + m_Description.Append(W("\n")); +} + //--------------------------------------------------------------------------------------- // // Generate an entry in EventLog. @@ -448,7 +476,6 @@ BOOL ShouldLogInEventLog() } CONTRACTL_END; -#ifndef FEATURE_CORESYSTEM // If the process is being debugged, don't log if ((CORDebuggerAttached() || IsDebuggerPresent()) #ifdef _DEBUG @@ -471,10 +498,6 @@ BOOL ShouldLogInEventLog() return FALSE; else return TRUE; -#else - // no event log on Apollo - return FALSE; -#endif //!FEATURE_CORESYSTEM } //--------------------------------------------------------------------------------------- diff --git a/src/vm/eventreporter.h b/src/vm/eventreporter.h index 54317133ddf7..0359eee7ace3 100644 --- a/src/vm/eventreporter.h +++ b/src/vm/eventreporter.h @@ -61,6 +61,8 @@ class EventReporter void BeginStackTrace(); // Add one frame to the callstack part void AddStackTrace(SString& s); + // Add failfast stack trace + void AddFailFastStackTrace(SString& s); // Report to the EventLog void Report(); }; From c7c4cd399bd37379735f3bc70c2959844d2cee3f Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Fri, 9 Mar 2018 17:17:30 -0800 Subject: [PATCH 02/12] change const wchar * to lpcwstr --- src/classlibnative/bcltype/system.cpp | 2 +- src/vm/crossgencompile.cpp | 2 +- src/vm/eepolicy.cpp | 8 ++++---- src/vm/eepolicy.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp index 57a4aa12dfea..a28adace88ab 100644 --- a/src/classlibnative/bcltype/system.cpp +++ b/src/classlibnative/bcltype/system.cpp @@ -460,7 +460,7 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce WszOutputDebugString(W("\"\r\n")); } - const WCHAR * argExceptionString = NULL; + LPCWSTR argExceptionString = NULL; StackSString msg; if (gc.refExceptionForWatsonBucketing != NULL) { diff --git a/src/vm/crossgencompile.cpp b/src/vm/crossgencompile.cpp index 790b0d817c66..f6a1338c84cf 100644 --- a/src/vm/crossgencompile.cpp +++ b/src/vm/crossgencompile.cpp @@ -384,7 +384,7 @@ extern "C" UINT_PTR STDCALL GetCurrentIP() return 0; } -void EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, const WCHAR * argExceptionString) +void EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, LPCWSTR argExceptionString) { fprintf(stderr, "Fatal error: %08x\n", exitCode); ExitProcess(exitCode); diff --git a/src/vm/eepolicy.cpp b/src/vm/eepolicy.cpp index d300276909a4..e15af92bfce5 100644 --- a/src/vm/eepolicy.cpp +++ b/src/vm/eepolicy.cpp @@ -1176,7 +1176,7 @@ inline void LogCallstackForLogWorker() // Return Value: // None // -inline void DoLogForFailFastException(LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, const WCHAR * argExceptionString) +inline void DoLogForFailFastException(LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, LPCWSTR argExceptionString) { WRAPPER_NO_CONTRACT; @@ -1205,7 +1205,7 @@ inline void DoLogForFailFastException(LPCWSTR pszMessage, PEXCEPTION_POINTERS pE PrintToStdErrA("\n"); PrintToStdErrA("Exception details:"); PrintToStdErrA("\n"); - PrintToStdErrW(argExceptionString); + PrintToStdErrW((WCHAR*)argExceptionString); PrintToStdErrA("\n"); } } @@ -1220,7 +1220,7 @@ inline void DoLogForFailFastException(LPCWSTR pszMessage, PEXCEPTION_POINTERS pE // Log an error to the event log if possible, then throw up a dialog box. // -void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, const WCHAR * argExceptionString) +void EEPolicy::LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, LPCWSTR argExceptionString) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_TRIGGERS; @@ -1491,7 +1491,7 @@ void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pE UNREACHABLE(); } -void DECLSPEC_NORETURN EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage /* = NULL */, PEXCEPTION_POINTERS pExceptionInfo /* = NULL */, LPCWSTR errorSource /* = NULL */, const WCHAR * argExceptionString /* = NULL */) +void DECLSPEC_NORETURN EEPolicy::HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pszMessage /* = NULL */, PEXCEPTION_POINTERS pExceptionInfo /* = NULL */, LPCWSTR errorSource /* = NULL */, LPCWSTR argExceptionString /* = NULL */) { WRAPPER_NO_CONTRACT; diff --git a/src/vm/eepolicy.h b/src/vm/eepolicy.h index c41d16bc09f6..44e0073754f0 100644 --- a/src/vm/eepolicy.h +++ b/src/vm/eepolicy.h @@ -124,7 +124,7 @@ class EEPolicy static void HandleExitProcess(ShutdownCompleteAction sca = SCA_ExitProcessWhenShutdownComplete); - static void DECLSPEC_NORETURN HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pMessage=NULL, PEXCEPTION_POINTERS pExceptionInfo= NULL, LPCWSTR errorSource=NULL, const WCHAR * argExceptionString=NULL); + static void DECLSPEC_NORETURN HandleFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pMessage=NULL, PEXCEPTION_POINTERS pExceptionInfo= NULL, LPCWSTR errorSource=NULL, LPCWSTR argExceptionString=NULL); static void DECLSPEC_NORETURN HandleFatalStackOverflow(EXCEPTION_POINTERS *pException, BOOL fSkipDebugger = FALSE); @@ -147,7 +147,7 @@ class EEPolicy BOOL IsValidActionForFailure(EClrFailure failure, EPolicyAction action); EPolicyAction GetFinalAction(EPolicyAction action, Thread *pThread); - static void LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, const WCHAR * argExceptionString=NULL); + static void LogFatalError(UINT exitCode, UINT_PTR address, LPCWSTR pMessage, PEXCEPTION_POINTERS pExceptionInfo, LPCWSTR errorSource, LPCWSTR argExceptionString=NULL); // IMPORTANT NOTE: only the following two functions should be calling ExitProcessViaShim. // - CorHost2::ExitProcess From 6f5861c0931a66c86baff2fb5d8191f69ca7808d Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Mon, 19 Mar 2018 12:57:06 -0700 Subject: [PATCH 03/12] Enable sending unhandled exception info to Windows Event Log --- src/vm/eventreporter.cpp | 55 +++++++++++----------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index aa4a13abc351..f066b4e446a8 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -721,53 +721,28 @@ void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) // We can also be here when in non-DefaultDomain an exception goes unhandled on a pure managed thread. In such a case, // we wont have CrossAppDomainMarshaledException instance but the original exception object that will be used to extract // the stack trace from. - if (pThread->GetDomain()->IsDefaultDomain()) + if (IsException(gc.throwable->GetMethodTable())) { - if (IsExceptionOfType(kCrossAppDomainMarshaledException, &(gc.throwable))) + SmallStackSString wordAt; + if (!wordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) { - // This is a CrossAppDomainMarshaledException instance - check if it has - // something for us in the Message property. - gc.originalExceptionMessage = ((EXCEPTIONREF)gc.throwable)->GetMessage(); - if (gc.originalExceptionMessage != NULL) - { - // Ok - so, we have details about the original exception. Add them to the - // EventReporter object so that they get written to the event log. - reporter.AddDescription(gc.originalExceptionMessage->GetBuffer()); - - LOG((LF_EH, LL_INFO100, "DoReportForUnhandledException - Added original exception details to EventReporter from CrossAppDomainMarshaledException object.\n")); - } - else - { - LOG((LF_EH, LL_INFO100, "DoReportForUnhandledException - Original exception details not present in CrossAppDomainMarshaledException object.\n")); - } - } - } - else - { - if (IsException(gc.throwable->GetMethodTable())) - { - SmallStackSString wordAt; - if (!wordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) - { - wordAt.Set(W(" at")); - } - else - { - wordAt.Insert(wordAt.Begin(), W(" ")); - } - wordAt += W(" "); - - ReportExceptionStackHelper(gc.throwable, reporter, wordAt, /* recursionLimit = */10); + wordAt.Set(W(" at")); } else { - TypeString::AppendType(s, TypeHandle(gc.throwable->GetMethodTable()), TypeString::FormatNamespace | TypeString::FormatFullInst); - reporter.AddDescription(s); - reporter.BeginStackTrace(); - LogCallstackForEventReporterWorker(reporter); + wordAt.Insert(wordAt.Begin(), W(" ")); } - } + wordAt += W(" "); + ReportExceptionStackHelper(gc.throwable, reporter, wordAt, /* recursionLimit = */10); + } + else + { + TypeString::AppendType(s, TypeHandle(gc.throwable->GetMethodTable()), TypeString::FormatNamespace | TypeString::FormatFullInst); + reporter.AddDescription(s); + reporter.BeginStackTrace(); + LogCallstackForEventReporterWorker(reporter); + } GCPROTECT_END(); } else From f2027fae57a9ea2488f4920b2b8210d9ef7a2be9 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Tue, 20 Mar 2018 04:14:41 -0700 Subject: [PATCH 04/12] Change log format to match console output and address PR comments --- src/vm/eventreporter.cpp | 46 +++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index f066b4e446a8..c3f94f3f0a8f 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -365,8 +365,15 @@ void EventReporter::AddFailFastStackTrace(SString& s) CONTRACTL_END; _ASSERTE(m_eventType == ERT_ManagedFailFast); - - m_Description.Append(W("Exception stack:\n")); + InlineSString<80> ssMessage; + if (!ssMessage.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTION)) + { + m_Description.Append(W("Exception stack:\n")); + } + else + { + m_Description.Append(ssMessage); + } m_Description.Append(s); m_Description.Append(W("\n")); } @@ -694,6 +701,7 @@ void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) { OBJECTREF throwable; STRINGREF originalExceptionMessage; + STRINGREF exceptionString; } gc; ZeroMemory(&gc, sizeof(gc)); @@ -718,23 +726,37 @@ void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) // look that up and if it is not empty, add those details to the EventReporter so that they get written to the // event log as well. // - // We can also be here when in non-DefaultDomain an exception goes unhandled on a pure managed thread. In such a case, - // we wont have CrossAppDomainMarshaledException instance but the original exception object that will be used to extract - // the stack trace from. if (IsException(gc.throwable->GetMethodTable())) { - SmallStackSString wordAt; - if (!wordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) + StackSString result; + // Assume we're calling Exception.InternalToString() ... + BinderMethodID sigID = METHOD__EXCEPTION__INTERNAL_TO_STRING; + + // Get the MethodDesc on which we'll call. + MethodDescCallSite toString(sigID, &(gc.throwable)); + + // Make the call. + ARG_SLOT arg[1] = { ObjToArgSlot(gc.throwable) }; + gc.exceptionString = toString.Call_RetSTRINGREF(arg); + if (gc.exceptionString != NULL) { - wordAt.Set(W(" at")); + gc.exceptionString->GetSString(result); + reporter.AddDescription(result); } else { - wordAt.Insert(wordAt.Begin(), W(" ")); + SmallStackSString wordAt; + if (!wordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) + { + wordAt.Set(W(" at")); + } + else + { + wordAt.Insert(wordAt.Begin(), W(" ")); + } + wordAt += W(" "); + ReportExceptionStackHelper(gc.throwable, reporter, wordAt, /* recursionLimit = */10); } - wordAt += W(" "); - - ReportExceptionStackHelper(gc.throwable, reporter, wordAt, /* recursionLimit = */10); } else { From b047c0460c72526b5d4e0ff92e5170bee51a5f8d Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Tue, 20 Mar 2018 04:27:29 -0700 Subject: [PATCH 05/12] Remove more comments --- src/vm/eventreporter.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index c3f94f3f0a8f..6dda0bb1e1d7 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -710,22 +710,6 @@ void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) gc.throwable = pThread->GetThrowable(); _ASSERTE(gc.throwable != NULL); - // On CoreCLR, managed code execution happens in non-default AppDomains and all threads have an AD transition - // at their base from DefaultDomain to the target Domain before they start executing managed code. Thus, when - // an exception goes unhandled in a non-default AppDomain on a reverse pinvoke thread, the original exception details are copied - // to the Message property of System.CrossAppDomainMarshaledException instance at the AD transition boundary, - // and the exception is then thrown in the calling AppDomain. This is done since CoreCLR does not support marshaling of - // objects across AppDomains. - // - // On SL, exceptions dont go unhandled to the OS. But in WLC, they can. Thus, when the scenario above happens for WLC, - // the OS will invoke CoreCLR's registered UEF and reach here to write the stacktrace from the - // exception object (which will be a CrossAppDomainMarshaledException instance) to the event log. At this point, - // we shall be in DefaultDomain. - // - // However, the original exception details are in the Message property of CrossAppDomainMarshaledException. So, we should - // look that up and if it is not empty, add those details to the EventReporter so that they get written to the - // event log as well. - // if (IsException(gc.throwable->GetMethodTable())) { StackSString result; From 71b8c1a68d93bebccc82fc0abaf362bfee7ef9db Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Wed, 21 Mar 2018 14:25:45 -0700 Subject: [PATCH 06/12] Change the order DoReportForUnhandledException to do a safety check first before calling managed code --- src/vm/eventreporter.cpp | 37 +++++++++++++++++++++++-------------- src/vm/eventreporter.h | 2 +- src/vm/excep.cpp | 21 +++++++++++++++------ src/vm/excep.h | 3 ++- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index 6dda0bb1e1d7..ee1bfb43d4b9 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -679,11 +679,12 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS // // Arguments: // pExceptionInfo - Exception information +// useManagedException - Flag to indicate whether it's okay to call Exception.ToString() // // Return Value: // None // -void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) +void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo, BOOL useManagedException) { WRAPPER_NO_CONTRACT; @@ -694,6 +695,7 @@ void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) EX_TRY { StackSString s; + bool doUnmanagedLogging = true; if (pThread && pThread->HasException() != NULL) { GCX_COOP(); @@ -712,22 +714,29 @@ void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) if (IsException(gc.throwable->GetMethodTable())) { - StackSString result; - // Assume we're calling Exception.InternalToString() ... - BinderMethodID sigID = METHOD__EXCEPTION__INTERNAL_TO_STRING; + // If we can use Exception.ToString(), we will use that to maintain consistency with what gets printed on Console + if (useManagedException) + { + StackSString result; + // Assume we're calling Exception.InternalToString() ... + BinderMethodID sigID = METHOD__EXCEPTION__INTERNAL_TO_STRING; - // Get the MethodDesc on which we'll call. - MethodDescCallSite toString(sigID, &(gc.throwable)); + // Get the MethodDesc on which we'll call. + MethodDescCallSite toString(sigID, &(gc.throwable)); - // Make the call. - ARG_SLOT arg[1] = { ObjToArgSlot(gc.throwable) }; - gc.exceptionString = toString.Call_RetSTRINGREF(arg); - if (gc.exceptionString != NULL) - { - gc.exceptionString->GetSString(result); - reporter.AddDescription(result); + // Make the call. + ARG_SLOT arg[1] = { ObjToArgSlot(gc.throwable) }; + gc.exceptionString = toString.Call_RetSTRINGREF(arg); + if (gc.exceptionString != NULL) + { + gc.exceptionString->GetSString(result); + reporter.AddDescription(result); + doUnmanagedLogging = false; + } } - else + + // Otherwise we fall back to native log + if (doUnmanagedLogging) { SmallStackSString wordAt; if (!wordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) diff --git a/src/vm/eventreporter.h b/src/vm/eventreporter.h index 0359eee7ace3..c2085b68912c 100644 --- a/src/vm/eventreporter.h +++ b/src/vm/eventreporter.h @@ -72,6 +72,6 @@ BOOL ShouldLogInEventLog(); // Record managed callstack in EventReporter. void LogCallstackForEventReporter(EventReporter& reporter); // Generate a report in EventLog for unhandled exception for both managed and unmanaged. -void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo); +void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo, BOOL shouldLogManaged); #endif // _eventreporter_h_ diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 09283f78391f..2b2e827786dc 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -5234,10 +5234,6 @@ LONG InternalUnhandledExceptionFilter_Worker( #endif // DEBUGGING_SUPPORTED -#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) - DoReportForUnhandledException(pParam->pExceptionInfo); -#endif // FEATURE_EVENT_TRACE - // // Except for notifying debugger, ignore exception if unmanaged, or // if it's a debugger-generated exception or user breakpoint exception. @@ -5257,10 +5253,16 @@ LONG InternalUnhandledExceptionFilter_Worker( LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker: Calling DefaultCatchHandler\n")); + BOOL useManagedExceptionLog = false; // Call our default catch handler to do the managed unhandled exception work. DefaultCatchHandler(pParam->pExceptionInfo, NULL, useLastThrownObject, - TRUE /*isTerminating*/, FALSE /*isThreadBaseFIlter*/, FALSE /*sendAppDomainEvents*/); + TRUE /*isTerminating*/, FALSE /*isThreadBaseFIlter*/, FALSE /*sendAppDomainEvents*/, &useManagedExceptionLog); + +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) + DoReportForUnhandledException(pParam->pExceptionInfo, useManagedExceptionLog); +#endif // FEATURE_EVENT_TRACE + lDone: ; } @@ -5544,7 +5546,8 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, BOOL useLastThrownObject, BOOL isTerminating, BOOL isThreadBaseFilter, - BOOL sendAppDomainEvents) + BOOL sendAppDomainEvents, + BOOL *useManagedExceptionLog) { CONTRACTL { @@ -5725,6 +5728,12 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, // this is stack heavy because of the CQuickWSTRBase, so we break it out // and don't have to carry the weight through our other code paths. DefaultCatchHandlerExceptionMessageWorker(pThread, throwable, buf, buf_size); + + // If this parameter was passed in, set it to true to indicate it's okay to use managed exception + if (useManagedExceptionLog) + { + *useManagedExceptionLog = true; + } } } EX_CATCH diff --git a/src/vm/excep.h b/src/vm/excep.h index 4261c3cff3c3..09e4853d04ed 100644 --- a/src/vm/excep.h +++ b/src/vm/excep.h @@ -241,7 +241,8 @@ void STDMETHODCALLTYPE DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionInfo, BOOL useLastThrownObject = FALSE, BOOL isTerminating = FALSE, BOOL isThreadBaseFilter = FALSE, - BOOL sendAppDomainEvents = TRUE); + BOOL sendAppDomainEvents = TRUE, + BOOL * shouldLogMessage = NULL); void ReplaceExceptionContextRecord(T_CONTEXT *pTarget, T_CONTEXT *pSource); From 6cba3fe5aba4ba5bf238df76d5271799f468c7d6 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Wed, 21 Mar 2018 14:27:25 -0700 Subject: [PATCH 07/12] Fix parameter name in header file --- src/vm/eventreporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/eventreporter.h b/src/vm/eventreporter.h index c2085b68912c..bbdd80c332a4 100644 --- a/src/vm/eventreporter.h +++ b/src/vm/eventreporter.h @@ -72,6 +72,6 @@ BOOL ShouldLogInEventLog(); // Record managed callstack in EventReporter. void LogCallstackForEventReporter(EventReporter& reporter); // Generate a report in EventLog for unhandled exception for both managed and unmanaged. -void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo, BOOL shouldLogManaged); +void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo, BOOL useManagedException); #endif // _eventreporter_h_ From 630bb87adde8ade53dad61f50a5f341b5890f7f4 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Wed, 21 Mar 2018 15:43:18 -0700 Subject: [PATCH 08/12] Add Windows Event logging in DefaultCatchHandler and remove DoReportForUnhandledException --- src/vm/eventreporter.cpp | 114 --------------------------------------- src/vm/eventreporter.h | 5 +- src/vm/excep.cpp | 34 ++++++------ src/vm/excep.h | 3 +- 4 files changed, 21 insertions(+), 135 deletions(-) diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index ee1bfb43d4b9..f8d3d7886735 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -673,120 +673,6 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS } -//--------------------------------------------------------------------------------------- -// -// Generate an EventLog entry for unhandled exception. -// -// Arguments: -// pExceptionInfo - Exception information -// useManagedException - Flag to indicate whether it's okay to call Exception.ToString() -// -// Return Value: -// None -// -void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo, BOOL useManagedException) -{ - WRAPPER_NO_CONTRACT; - - if (ShouldLogInEventLog()) - { - Thread *pThread = GetThread(); - EventReporter reporter(EventReporter::ERT_UnhandledException); - EX_TRY - { - StackSString s; - bool doUnmanagedLogging = true; - if (pThread && pThread->HasException() != NULL) - { - GCX_COOP(); - struct - { - OBJECTREF throwable; - STRINGREF originalExceptionMessage; - STRINGREF exceptionString; - } gc; - ZeroMemory(&gc, sizeof(gc)); - - GCPROTECT_BEGIN(gc); - - gc.throwable = pThread->GetThrowable(); - _ASSERTE(gc.throwable != NULL); - - if (IsException(gc.throwable->GetMethodTable())) - { - // If we can use Exception.ToString(), we will use that to maintain consistency with what gets printed on Console - if (useManagedException) - { - StackSString result; - // Assume we're calling Exception.InternalToString() ... - BinderMethodID sigID = METHOD__EXCEPTION__INTERNAL_TO_STRING; - - // Get the MethodDesc on which we'll call. - MethodDescCallSite toString(sigID, &(gc.throwable)); - - // Make the call. - ARG_SLOT arg[1] = { ObjToArgSlot(gc.throwable) }; - gc.exceptionString = toString.Call_RetSTRINGREF(arg); - if (gc.exceptionString != NULL) - { - gc.exceptionString->GetSString(result); - reporter.AddDescription(result); - doUnmanagedLogging = false; - } - } - - // Otherwise we fall back to native log - if (doUnmanagedLogging) - { - SmallStackSString wordAt; - if (!wordAt.LoadResource(CCompRC::Optional, IDS_ER_WORDAT)) - { - wordAt.Set(W(" at")); - } - else - { - wordAt.Insert(wordAt.Begin(), W(" ")); - } - wordAt += W(" "); - ReportExceptionStackHelper(gc.throwable, reporter, wordAt, /* recursionLimit = */10); - } - } - else - { - TypeString::AppendType(s, TypeHandle(gc.throwable->GetMethodTable()), TypeString::FormatNamespace | TypeString::FormatFullInst); - reporter.AddDescription(s); - reporter.BeginStackTrace(); - LogCallstackForEventReporterWorker(reporter); - } - GCPROTECT_END(); - } - else - { - InlineSString<80> ssErrorFormat; - if(!ssErrorFormat.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTIONINFO)) - ssErrorFormat.Set(W("exception code %1, exception address %2")); - SmallStackSString exceptionCodeString; - exceptionCodeString.Printf(W("%x"), pExceptionInfo->ExceptionRecord->ExceptionCode); - SmallStackSString addressString; - addressString.Printf(W("%p"), (UINT_PTR)pExceptionInfo->ExceptionRecord->ExceptionAddress); - s.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)ssErrorFormat, 0, 0, exceptionCodeString, addressString); - reporter.AddDescription(s); - if (pThread) - { - LogCallstackForEventReporter(reporter); - } - } - } - EX_CATCH - { - // We are reporting an exception. If we throw while working on this, it is not fatal. - } - EX_END_CATCH(SwallowAllExceptions); - - reporter.Report(); - } -} - // This function will return the product version of CoreCLR // instance we are executing in. void EventReporter::GetCoreCLRInstanceProductVersion(DWORD * pdwMajor, DWORD * pdwMinor, DWORD * pdwBuild, DWORD * pdwRevision) diff --git a/src/vm/eventreporter.h b/src/vm/eventreporter.h index bbdd80c332a4..69307f07896a 100644 --- a/src/vm/eventreporter.h +++ b/src/vm/eventreporter.h @@ -71,7 +71,6 @@ class EventReporter BOOL ShouldLogInEventLog(); // Record managed callstack in EventReporter. void LogCallstackForEventReporter(EventReporter& reporter); -// Generate a report in EventLog for unhandled exception for both managed and unmanaged. -void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo, BOOL useManagedException); - +// Helper method for logging stack trace in EventReporter +void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallStackSString& wordAt, int recursionLimit); #endif // _eventreporter_h_ diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 2b2e827786dc..4b6825bb9493 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -5253,16 +5253,9 @@ LONG InternalUnhandledExceptionFilter_Worker( LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker: Calling DefaultCatchHandler\n")); - BOOL useManagedExceptionLog = false; - // Call our default catch handler to do the managed unhandled exception work. DefaultCatchHandler(pParam->pExceptionInfo, NULL, useLastThrownObject, - TRUE /*isTerminating*/, FALSE /*isThreadBaseFIlter*/, FALSE /*sendAppDomainEvents*/, &useManagedExceptionLog); - -#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) - DoReportForUnhandledException(pParam->pExceptionInfo, useManagedExceptionLog); -#endif // FEATURE_EVENT_TRACE - + TRUE /*isTerminating*/, FALSE /*isThreadBaseFIlter*/, FALSE /*sendAppDomainEvents*/); lDone: ; } @@ -5534,6 +5527,22 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, } PrintToStdErrA("\n"); + + // Send the log to Windows Event Log + EX_TRY + { + EventReporter reporter(EventReporter::ERT_UnhandledException); + if (!message.IsEmpty()) + { + reporter.AddDescription(message); + } + reporter.Report(); + } + EX_CATCH + { + } + EX_END_CATCH(SwallowAllExceptions); + } } @@ -5546,8 +5555,7 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, BOOL useLastThrownObject, BOOL isTerminating, BOOL isThreadBaseFilter, - BOOL sendAppDomainEvents, - BOOL *useManagedExceptionLog) + BOOL sendAppDomainEvents) { CONTRACTL { @@ -5728,12 +5736,6 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, // this is stack heavy because of the CQuickWSTRBase, so we break it out // and don't have to carry the weight through our other code paths. DefaultCatchHandlerExceptionMessageWorker(pThread, throwable, buf, buf_size); - - // If this parameter was passed in, set it to true to indicate it's okay to use managed exception - if (useManagedExceptionLog) - { - *useManagedExceptionLog = true; - } } } EX_CATCH diff --git a/src/vm/excep.h b/src/vm/excep.h index 09e4853d04ed..4261c3cff3c3 100644 --- a/src/vm/excep.h +++ b/src/vm/excep.h @@ -241,8 +241,7 @@ void STDMETHODCALLTYPE DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionInfo, BOOL useLastThrownObject = FALSE, BOOL isTerminating = FALSE, BOOL isThreadBaseFilter = FALSE, - BOOL sendAppDomainEvents = TRUE, - BOOL * shouldLogMessage = NULL); + BOOL sendAppDomainEvents = TRUE); void ReplaceExceptionContextRecord(T_CONTEXT *pTarget, T_CONTEXT *pSource); From 77c7e4ecbcaee35058f947500e45ff2d6bb7d03b Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Sat, 24 Mar 2018 02:26:37 -0700 Subject: [PATCH 09/12] Add back event reporting for ignored unhandled exception cases, fix broken UNIX builds --- src/vm/eventreporter.cpp | 45 ++++++++++++++++++++++++++++++++++++++++ src/vm/eventreporter.h | 2 ++ src/vm/excep.cpp | 34 ++++++++++++++++++------------ src/vm/excep.h | 3 ++- 4 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index f8d3d7886735..87980d570a42 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -673,6 +673,51 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS } +//--------------------------------------------------------------------------------------- +// +// Generate an EventLog entry for unhandled exceptions that are not sent to DefaultCatchHandler. +// +// Arguments: +// pExceptionInfo - Exception information +// +// Return Value: +// None +// +void DoReportForIgnoredUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) +{ + WRAPPER_NO_CONTRACT; + + if (ShouldLogInEventLog()) + { + Thread *pThread = GetThread(); + EventReporter reporter(EventReporter::ERT_UnhandledException); + EX_TRY + { + StackSString s; + InlineSString<80> ssErrorFormat; + if (!ssErrorFormat.LoadResource(CCompRC::Optional, IDS_ER_UNHANDLEDEXCEPTIONINFO)) + ssErrorFormat.Set(W("exception code %1, exception address %2")); + SmallStackSString exceptionCodeString; + exceptionCodeString.Printf(W("%x"), pExceptionInfo->ExceptionRecord->ExceptionCode); + SmallStackSString addressString; + addressString.Printf(W("%p"), (UINT_PTR)pExceptionInfo->ExceptionRecord->ExceptionAddress); + s.FormatMessage(FORMAT_MESSAGE_FROM_STRING, (LPCWSTR)ssErrorFormat, 0, 0, exceptionCodeString, addressString); + reporter.AddDescription(s); + if (pThread) + { + LogCallstackForEventReporter(reporter); + } + } + EX_CATCH + { + // We are reporting an exception. If we throw while working on this, it is not fatal. + } + EX_END_CATCH(SwallowAllExceptions); + + reporter.Report(); + } +} + // This function will return the product version of CoreCLR // instance we are executing in. void EventReporter::GetCoreCLRInstanceProductVersion(DWORD * pdwMajor, DWORD * pdwMinor, DWORD * pdwBuild, DWORD * pdwRevision) diff --git a/src/vm/eventreporter.h b/src/vm/eventreporter.h index 69307f07896a..7eaf28027520 100644 --- a/src/vm/eventreporter.h +++ b/src/vm/eventreporter.h @@ -71,6 +71,8 @@ class EventReporter BOOL ShouldLogInEventLog(); // Record managed callstack in EventReporter. void LogCallstackForEventReporter(EventReporter& reporter); +// Record unhandled exceptions that are not handled by DefaultCatchHandler. +void DoReportForIgnoredUnhandledException(PEXCEPTION_POINTERS pExceptionInfo); // Helper method for logging stack trace in EventReporter void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallStackSString& wordAt, int recursionLimit); #endif // _eventreporter_h_ diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 4b6825bb9493..0b6b79ea8b8a 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -5241,6 +5241,7 @@ LONG InternalUnhandledExceptionFilter_Worker( if (tore.GetType() == TypeOfReportedError::NativeThreadUnhandledException) { pParam->retval = EXCEPTION_CONTINUE_SEARCH; + DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); goto lDone; } @@ -5248,6 +5249,7 @@ LONG InternalUnhandledExceptionFilter_Worker( { LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker, ignoring the exception\n")); pParam->retval = EXCEPTION_CONTINUE_SEARCH; + DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); goto lDone; } @@ -5505,7 +5507,8 @@ void STDMETHODCALLTYPE DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, OBJECTREF throwable, __inout_ecount(buf_size) WCHAR *buf, - const int buf_size) + const int buf_size, + BOOL sendWindowsEventLog) { if (throwable != NULL) { @@ -5528,21 +5531,25 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, PrintToStdErrA("\n"); +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) // Send the log to Windows Event Log - EX_TRY + if (sendWindowsEventLog) { - EventReporter reporter(EventReporter::ERT_UnhandledException); - if (!message.IsEmpty()) + EX_TRY { - reporter.AddDescription(message); + EventReporter reporter(EventReporter::ERT_UnhandledException); + if (!message.IsEmpty()) + { + reporter.AddDescription(message); + } + reporter.Report(); } - reporter.Report(); - } - EX_CATCH - { + EX_CATCH + { + } + EX_END_CATCH(SwallowAllExceptions); } - EX_END_CATCH(SwallowAllExceptions); - +#endif } } @@ -5555,7 +5562,8 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, BOOL useLastThrownObject, BOOL isTerminating, BOOL isThreadBaseFilter, - BOOL sendAppDomainEvents) + BOOL sendAppDomainEvents, + BOOL sendWindowsEventLog) { CONTRACTL { @@ -5735,7 +5743,7 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers, { // this is stack heavy because of the CQuickWSTRBase, so we break it out // and don't have to carry the weight through our other code paths. - DefaultCatchHandlerExceptionMessageWorker(pThread, throwable, buf, buf_size); + DefaultCatchHandlerExceptionMessageWorker(pThread, throwable, buf, buf_size, sendWindowsEventLog); } } EX_CATCH diff --git a/src/vm/excep.h b/src/vm/excep.h index 4261c3cff3c3..6df9a98452ab 100644 --- a/src/vm/excep.h +++ b/src/vm/excep.h @@ -241,7 +241,8 @@ void STDMETHODCALLTYPE DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionInfo, BOOL useLastThrownObject = FALSE, BOOL isTerminating = FALSE, BOOL isThreadBaseFilter = FALSE, - BOOL sendAppDomainEvents = TRUE); + BOOL sendAppDomainEvents = TRUE, + BOOL sendWindowsEventLog = FALSE); void ReplaceExceptionContextRecord(T_CONTEXT *pTarget, T_CONTEXT *pSource); From f0ae4c312229e9c5b8ac5b0aa0e2a2340e741de2 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Mon, 26 Mar 2018 12:06:17 -0700 Subject: [PATCH 10/12] Fix more broken unix builds --- src/vm/excep.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 0b6b79ea8b8a..3a419b2311af 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -5241,7 +5241,9 @@ LONG InternalUnhandledExceptionFilter_Worker( if (tore.GetType() == TypeOfReportedError::NativeThreadUnhandledException) { pParam->retval = EXCEPTION_CONTINUE_SEARCH; +#ifdef defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); +#endif goto lDone; } @@ -5249,7 +5251,9 @@ LONG InternalUnhandledExceptionFilter_Worker( { LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker, ignoring the exception\n")); pParam->retval = EXCEPTION_CONTINUE_SEARCH; +#ifdef defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); +#endif goto lDone; } From aa80194b45ca4f8d284fed92208e13daa14773d4 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Mon, 26 Mar 2018 12:20:17 -0700 Subject: [PATCH 11/12] Fix typo --- src/vm/excep.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 3a419b2311af..4d8b74de9543 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -5241,7 +5241,7 @@ LONG InternalUnhandledExceptionFilter_Worker( if (tore.GetType() == TypeOfReportedError::NativeThreadUnhandledException) { pParam->retval = EXCEPTION_CONTINUE_SEARCH; -#ifdef defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); #endif goto lDone; @@ -5251,7 +5251,7 @@ LONG InternalUnhandledExceptionFilter_Worker( { LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker, ignoring the exception\n")); pParam->retval = EXCEPTION_CONTINUE_SEARCH; -#ifdef defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); #endif goto lDone; From 9ac8592b22f5c6b384af3dbde937b7d463f1a837 Mon Sep 17 00:00:00 2001 From: Sung Yoon Whang Date: Tue, 27 Mar 2018 13:01:52 -0700 Subject: [PATCH 12/12] Address PR comments --- src/vm/eventreporter.cpp | 2 +- src/vm/eventreporter.h | 4 ++-- src/vm/excep.cpp | 30 ++++++++++++++++++++++-------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp index 87980d570a42..74362802dcde 100644 --- a/src/vm/eventreporter.cpp +++ b/src/vm/eventreporter.cpp @@ -683,7 +683,7 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS // Return Value: // None // -void DoReportForIgnoredUnhandledException(PEXCEPTION_POINTERS pExceptionInfo) +void DoReportForUnhandledNativeException(PEXCEPTION_POINTERS pExceptionInfo) { WRAPPER_NO_CONTRACT; diff --git a/src/vm/eventreporter.h b/src/vm/eventreporter.h index 7eaf28027520..abd35befc48f 100644 --- a/src/vm/eventreporter.h +++ b/src/vm/eventreporter.h @@ -71,8 +71,8 @@ class EventReporter BOOL ShouldLogInEventLog(); // Record managed callstack in EventReporter. void LogCallstackForEventReporter(EventReporter& reporter); -// Record unhandled exceptions that are not handled by DefaultCatchHandler. -void DoReportForIgnoredUnhandledException(PEXCEPTION_POINTERS pExceptionInfo); +// Record unhandled native exceptions. +void DoReportForUnhandledNativeException(PEXCEPTION_POINTERS pExceptionInfo); // Helper method for logging stack trace in EventReporter void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallStackSString& wordAt, int recursionLimit); #endif // _eventreporter_h_ diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index 4d8b74de9543..3ba3d05a82f2 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -28,6 +28,7 @@ #include "shimload.h" #include "eeconfig.h" #include "virtualcallstub.h" +#include "typestring.h" #ifndef FEATURE_PAL #include "dwreport.h" @@ -5242,7 +5243,7 @@ LONG InternalUnhandledExceptionFilter_Worker( { pParam->retval = EXCEPTION_CONTINUE_SEARCH; #if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) - DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); + DoReportForUnhandledNativeException(pParam->pExceptionInfo); #endif goto lDone; } @@ -5252,7 +5253,7 @@ LONG InternalUnhandledExceptionFilter_Worker( LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker, ignoring the exception\n")); pParam->retval = EXCEPTION_CONTINUE_SEARCH; #if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) - DoReportForIgnoredUnhandledException(pParam->pExceptionInfo); + DoReportForUnhandledNativeException(pParam->pExceptionInfo); #endif goto lDone; } @@ -5261,7 +5262,7 @@ LONG InternalUnhandledExceptionFilter_Worker( // Call our default catch handler to do the managed unhandled exception work. DefaultCatchHandler(pParam->pExceptionInfo, NULL, useLastThrownObject, - TRUE /*isTerminating*/, FALSE /*isThreadBaseFIlter*/, FALSE /*sendAppDomainEvents*/); + TRUE /*isTerminating*/, FALSE /*isThreadBaseFIlter*/, FALSE /*sendAppDomainEvents*/, TRUE /* sendWindowsEventLog */); lDone: ; } @@ -5514,6 +5515,7 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, const int buf_size, BOOL sendWindowsEventLog) { + GCPROTECT_BEGIN(throwable); if (throwable != NULL) { PrintToStdErrA("\n"); @@ -5537,24 +5539,36 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread, #if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) // Send the log to Windows Event Log - if (sendWindowsEventLog) + if (sendWindowsEventLog && ShouldLogInEventLog()) { EX_TRY { EventReporter reporter(EventReporter::ERT_UnhandledException); - if (!message.IsEmpty()) + + if (IsException(throwable->GetMethodTable())) + { + if (!message.IsEmpty()) + { + reporter.AddDescription(message); + } + reporter.Report(); + } + else { - reporter.AddDescription(message); + StackSString s; + TypeString::AppendType(s, TypeHandle(throwable->GetMethodTable()), TypeString::FormatNamespace | TypeString::FormatFullInst); + reporter.AddDescription(s); + LogCallstackForEventReporter(reporter); } - reporter.Report(); } - EX_CATCH + EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); } #endif } + GCPROTECT_END(); } //******************************************************************************