summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/classlibnative/bcltype/system.cpp2
-rw-r--r--src/vm/crossgencompile.cpp2
-rw-r--r--src/vm/eepolicy.cpp15
-rw-r--r--src/vm/eepolicy.h4
-rw-r--r--src/vm/eventreporter.cpp160
-rw-r--r--src/vm/eventreporter.h9
-rw-r--r--src/vm/excep.cpp55
-rw-r--r--src/vm/excep.h3
8 files changed, 120 insertions, 130 deletions
diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp
index 57a4aa12df..a28adace88 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 cea93bff57..f608afcad4 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 bdfe0fbf67..e15af92bfc 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;
@@ -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);
}
@@ -1486,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 c41d16bc09..44e0073754 100644
--- a/src/vm/eepolicy.h
+++ b/src/vm/eepolicy.h
@@ -124,7 +124,7 @@ public:
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 @@ private:
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
diff --git a/src/vm/eventreporter.cpp b/src/vm/eventreporter.cpp
index c73af36b55..74362802dc 100644
--- a/src/vm/eventreporter.cpp
+++ b/src/vm/eventreporter.cpp
@@ -345,6 +345,41 @@ 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);
+ 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"));
+}
+
+//---------------------------------------------------------------------------------------
+//
// Generate an entry in EventLog.
//
// Arguments:
@@ -448,7 +483,6 @@ BOOL ShouldLogInEventLog()
}
CONTRACTL_END;
-#ifndef FEATURE_CORESYSTEM
// If the process is being debugged, don't log
if ((CORDebuggerAttached() || IsDebuggerPresent())
#ifdef _DEBUG
@@ -471,10 +505,6 @@ BOOL ShouldLogInEventLog()
return FALSE;
else
return TRUE;
-#else
- // no event log on Apollo
- return FALSE;
-#endif //!FEATURE_CORESYSTEM
}
//---------------------------------------------------------------------------------------
@@ -645,7 +675,7 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS
//---------------------------------------------------------------------------------------
//
-// Generate an EventLog entry for unhandled exception.
+// Generate an EventLog entry for unhandled exceptions that are not sent to DefaultCatchHandler.
//
// Arguments:
// pExceptionInfo - Exception information
@@ -653,10 +683,10 @@ void ReportExceptionStackHelper(OBJECTREF exObj, EventReporter& reporter, SmallS
// Return Value:
// None
//
-void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo)
+void DoReportForUnhandledNativeException(PEXCEPTION_POINTERS pExceptionInfo)
{
WRAPPER_NO_CONTRACT;
-
+
if (ShouldLogInEventLog())
{
Thread *pThread = GetThread();
@@ -664,107 +694,21 @@ void DoReportForUnhandledException(PEXCEPTION_POINTERS pExceptionInfo)
EX_TRY
{
StackSString s;
- if (pThread && pThread->HasException() != NULL)
- {
- GCX_COOP();
- struct
- {
- OBJECTREF throwable;
- STRINGREF originalExceptionMessage;
- } gc;
- ZeroMemory(&gc, sizeof(gc));
-
- GCPROTECT_BEGIN(gc);
-
- 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.
- //
- // 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 (IsExceptionOfType(kCrossAppDomainMarshaledException, &(gc.throwable)))
- {
- // 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);
- }
- 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);
- }
- }
+ 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
+ EX_CATCH
{
// We are reporting an exception. If we throw while working on this, it is not fatal.
}
diff --git a/src/vm/eventreporter.h b/src/vm/eventreporter.h
index 54317133dd..abd35befc4 100644
--- a/src/vm/eventreporter.h
+++ b/src/vm/eventreporter.h
@@ -61,6 +61,8 @@ public:
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();
};
@@ -69,7 +71,8 @@ public:
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);
-
+// 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 09283f7839..3ba3d05a82 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"
@@ -5234,10 +5235,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.
@@ -5245,6 +5242,9 @@ LONG InternalUnhandledExceptionFilter_Worker(
if (tore.GetType() == TypeOfReportedError::NativeThreadUnhandledException)
{
pParam->retval = EXCEPTION_CONTINUE_SEARCH;
+#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL)
+ DoReportForUnhandledNativeException(pParam->pExceptionInfo);
+#endif
goto lDone;
}
@@ -5252,15 +5252,17 @@ 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)
+ DoReportForUnhandledNativeException(pParam->pExceptionInfo);
+#endif
goto lDone;
}
LOG((LF_EH, LL_INFO100, "InternalUnhandledExceptionFilter_Worker: Calling DefaultCatchHandler\n"));
-
// 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: ;
}
@@ -5510,8 +5512,10 @@ void STDMETHODCALLTYPE
DefaultCatchHandlerExceptionMessageWorker(Thread* pThread,
OBJECTREF throwable,
__inout_ecount(buf_size) WCHAR *buf,
- const int buf_size)
+ const int buf_size,
+ BOOL sendWindowsEventLog)
{
+ GCPROTECT_BEGIN(throwable);
if (throwable != NULL)
{
PrintToStdErrA("\n");
@@ -5532,7 +5536,39 @@ DefaultCatchHandlerExceptionMessageWorker(Thread* pThread,
}
PrintToStdErrA("\n");
+
+#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL)
+ // Send the log to Windows Event Log
+ if (sendWindowsEventLog && ShouldLogInEventLog())
+ {
+ EX_TRY
+ {
+ EventReporter reporter(EventReporter::ERT_UnhandledException);
+
+ if (IsException(throwable->GetMethodTable()))
+ {
+ if (!message.IsEmpty())
+ {
+ reporter.AddDescription(message);
+ }
+ reporter.Report();
+ }
+ else
+ {
+ StackSString s;
+ TypeString::AppendType(s, TypeHandle(throwable->GetMethodTable()), TypeString::FormatNamespace | TypeString::FormatFullInst);
+ reporter.AddDescription(s);
+ LogCallstackForEventReporter(reporter);
+ }
+ }
+ EX_CATCH
+ {
+ }
+ EX_END_CATCH(SwallowAllExceptions);
+ }
+#endif
}
+ GCPROTECT_END();
}
//******************************************************************************
@@ -5544,7 +5580,8 @@ DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionPointers,
BOOL useLastThrownObject,
BOOL isTerminating,
BOOL isThreadBaseFilter,
- BOOL sendAppDomainEvents)
+ BOOL sendAppDomainEvents,
+ BOOL sendWindowsEventLog)
{
CONTRACTL
{
@@ -5724,7 +5761,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 4261c3cff3..6df9a98452 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);