summaryrefslogtreecommitdiff
path: root/src/vm/excep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/excep.cpp')
-rw-r--r--src/vm/excep.cpp212
1 files changed, 59 insertions, 153 deletions
diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp
index 3ba3d05a82..9cb1296204 100644
--- a/src/vm/excep.cpp
+++ b/src/vm/excep.cpp
@@ -126,7 +126,6 @@ BOOL __stdcall IsExceptionFromManagedCodeCallback(EXCEPTION_RECORD * pExceptionR
SO_TOLERANT;
SUPPORTS_DAC;
PRECONDITION(CheckPointer(pExceptionRecord));
- PRECONDITION(!RunningOnWin7());
} CONTRACTL_END;
// If we can't enter the EE, done.
@@ -4083,49 +4082,6 @@ void DisableOSWatson(void)
LOG((LF_EH, LL_INFO100, "DisableOSWatson: SetErrorMode = 0x%x\n", lastErrorMode | SEM_NOGPFAULTERRORBOX));
}
-
-
-//----------------------------------------------------------------------------
-//
-// RaiseFailFastExceptionOnWin7 - invoke RaiseFailFastException on Win7
-//
-// Arguments:
-// pExceptionRecord - pointer to exception record
-// pContext - pointer to exception context
-//
-// Return Value:
-// None
-//
-// Note:
-// RaiseFailFastException will not return unless a debugger is attached
-// and the user chooses to keep going.
-//
-//----------------------------------------------------------------------------
-void RaiseFailFastExceptionOnWin7(PEXCEPTION_RECORD pExceptionRecord, PCONTEXT pContext)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(RunningOnWin7());
-
-#ifndef FEATURE_CORESYSTEM
- typedef void (WINAPI * RaiseFailFastExceptionFnPtr)(PEXCEPTION_RECORD, PCONTEXT, DWORD);
- RaiseFailFastExceptionFnPtr RaiseFailFastException;
-
- HINSTANCE hKernel32 = WszGetModuleHandle(WINDOWS_KERNEL32_DLLNAME_W);
- if (hKernel32 == NULL)
- return;
-
- RaiseFailFastException = (RaiseFailFastExceptionFnPtr)GetProcAddress(hKernel32, "RaiseFailFastException");
- if (RaiseFailFastException == NULL)
- return;
-#endif
-
- // enable preemptive mode before call into OS to allow runtime suspend to finish
- GCX_PREEMP();
-
- STRESS_LOG0(LF_CORDB,LL_INFO10, "D::RFFE: About to call RaiseFailFastException\n");
- RaiseFailFastException(pExceptionRecord, pContext, 0);
- STRESS_LOG0(LF_CORDB,LL_INFO10, "D::RFFE: Return from RaiseFailFastException\n");
-}
#endif // !FEATURE_PAL
//------------------------------------------------------------------------------
@@ -4196,133 +4152,83 @@ LONG WatsonLastChance( // EXCEPTION_CONTINUE_SEARCH, _CONTINUE_
LOG((LF_EH, LL_INFO10, "WatsonLastChance: Debugger not attached at sp %p ...\n", GetCurrentSP()));
#ifndef FEATURE_PAL
- BOOL bRunDoFaultReport = TRUE;
FaultReportResult result = FaultReportResultQuit;
- if (RunningOnWin7())
+ BOOL fSOException = FALSE;
+
+ if ((pExceptionInfo != NULL) &&
+ (pExceptionInfo->ExceptionRecord != NULL) &&
+ (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW))
{
- BOOL fSOException = FALSE;
+ fSOException = TRUE;
+ }
- if ((pExceptionInfo != NULL) &&
- (pExceptionInfo->ExceptionRecord != NULL) &&
- (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW))
- {
- fSOException = TRUE;
- }
+ if (g_pDebugInterface)
+ {
+ // we are about to let the OS trigger jit attach, however we need to synchronize with our
+ // own jit attach that we might be doing on another thread
+ // PreJitAttach races this thread against any others which might be attaching and if some other
+ // thread is doing it then we wait for its attach to complete first
+ g_pDebugInterface->PreJitAttach(TRUE, FALSE, FALSE);
+ }
- if (g_pDebugInterface)
+ // Let unhandled excpetions except stack overflow go to the OS
+ if (tore.IsUnhandledException() && !fSOException)
+ {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (tore.IsUserBreakpoint())
+ {
+ DoReportFault(pExceptionInfo);
+ }
+ else
+ {
+ BOOL fWatsonAlreadyLaunched = FALSE;
+ if (FastInterlockCompareExchange(&g_watsonAlreadyLaunched, 1, 0) != 0)
{
- // we are about to let the OS trigger jit attach, however we need to synchronize with our
- // own jit attach that we might be doing on another thread
- // PreJitAttach races this thread against any others which might be attaching and if some other
- // thread is doing it then we wait for its attach to complete first
- g_pDebugInterface->PreJitAttach(TRUE, FALSE, FALSE);
+ fWatsonAlreadyLaunched = TRUE;
}
- // Let unhandled excpetions except stack overflow go to the OS
- if (tore.IsUnhandledException() && !fSOException)
- {
- return EXCEPTION_CONTINUE_SEARCH;
- }
- else if (tore.IsUserBreakpoint())
- {
- DoReportFault(pExceptionInfo);
- }
- else
+ // Logic to avoid double prompt if more than one threads calling into WatsonLastChance
+ if (!fWatsonAlreadyLaunched)
{
- BOOL fWatsonAlreadyLaunched = FALSE;
- if (FastInterlockCompareExchange(&g_watsonAlreadyLaunched, 1, 0) != 0)
+ // EEPolicy::HandleFatalStackOverflow pushes a FaultingExceptionFrame on the stack after SO
+ // exception. Our hijack code runs in the exception context, and overwrites the stack space
+ // after SO excpetion, so we need to pop up this frame before invoking RaiseFailFast.
+ // This cumbersome code should be removed once SO synchronization is moved to be completely
+ // out-of-process.
+ if (fSOException && pThread && pThread->GetFrame() != FRAME_TOP)
{
- fWatsonAlreadyLaunched = TRUE;
+ GCX_COOP(); // Must be cooperative to modify frame chain.
+ pThread->GetFrame()->Pop(pThread);
}
- // Logic to avoid double prompt if more than one threads calling into WatsonLastChance
- if (!fWatsonAlreadyLaunched)
- {
- // EEPolicy::HandleFatalStackOverflow pushes a FaultingExceptionFrame on the stack after SO
- // exception. Our hijack code runs in the exception context, and overwrites the stack space
- // after SO excpetion, so we need to pop up this frame before invoking RaiseFailFast.
- // This cumbersome code should be removed once SO synchronization is moved to be completely
- // out-of-process.
- if (fSOException && pThread && pThread->GetFrame() != FRAME_TOP)
- {
- GCX_COOP(); // Must be cooperative to modify frame chain.
- pThread->GetFrame()->Pop(pThread);
- }
-
- LOG((LF_EH, LL_INFO10, "D::WLC: Call RaiseFailFastExceptionOnWin7\n"));
- RaiseFailFastExceptionOnWin7(pExceptionInfo == NULL ? NULL : pExceptionInfo->ExceptionRecord,
- pExceptionInfo == NULL ? NULL : pExceptionInfo->ContextRecord);
- STRESS_LOG0(LF_CORDB,LL_INFO10, "D::WLC: Return from RaiseFailFastExceptionOnWin7\n");
- }
- }
-
- if (g_pDebugInterface)
- {
- // if execution resumed here then we may or may not be attached
- // either way we need to end the attach process and unblock any other
- // threads which were waiting for the attach here to complete
- g_pDebugInterface->PostJitAttach();
- }
+ LOG((LF_EH, LL_INFO10, "D::WLC: Call RaiseFailFastExceptionOnWin7\n"));
+ // enable preemptive mode before call into OS to allow runtime suspend to finish
+ GCX_PREEMP();
- if (IsDebuggerPresent())
- {
- result = FaultReportResultDebug;
- jitAttachRequested = FALSE;
+ STRESS_LOG0(LF_CORDB, LL_INFO10, "D::RFFE: About to call RaiseFailFastException\n");
+ RaiseFailFastException(pExceptionInfo == NULL ? NULL : pExceptionInfo->ExceptionRecord,
+ pExceptionInfo == NULL ? NULL : pExceptionInfo->ContextRecord,
+ 0);
+ STRESS_LOG0(LF_CORDB, LL_INFO10, "D::RFFE: Return from RaiseFailFastException\n");
}
}
- else
+
+ if (g_pDebugInterface)
{
- // If we've got a fatal error but Watson isn't enabled, then fall back to old-style non-managed-aware
- // error reporting using faultrep to try and ensure we get an error report about this fatal error.
- if (!IsWatsonEnabled() && tore.IsFatalError() && (pExceptionInfo != NULL))
- {
- EFaultRepRetVal r = DoReportFault(pExceptionInfo);
- if (r != frrvErr && r != frrvErrNoDW && r != frrvErrTimeout)
- {
- // Once native Watson is sucessfully launched, we should not try to launch
- // our fake Watson dailog box.
- bRunDoFaultReport = FALSE;
- }
- }
+ // if execution resumed here then we may or may not be attached
+ // either way we need to end the attach process and unblock any other
+ // threads which were waiting for the attach here to complete
+ g_pDebugInterface->PostJitAttach();
+ }
- if (bRunDoFaultReport)
- {
- // http://devdiv/sites/docs/NetFX4/CLR/Specs/Developer%20Services/Error%20Reporting/WER%20SxS%20DCR.doc
- //
- // Watson SxS support for Desktop CLR
- //
- // For an unhandled exception thrown from native code, the first runtime that encounters the
- // unhandled native exception will report Watson if it is allowed by Watson SxS manager to do
- // Watson. If more than one runtimes attempt to report Watson concurrently, only one runtims
- // will be bestowed to report Watson. The result is that at most one Watson report will be
- // submitted for a process.
- //
- // To coordinate Watson reporting among runtimes in a process, Watson SxS manager, which is part
- // of the shim, will provide a new set of APIs, and keeps a status of whether a Watson report
- // has been submitted for a process.
- //
- // Each runtime registers an exception claiming callack with Watson SxS manager at startup.
- // Watson SxS manager provide an exception claiming API, which iterators through registerd
- // exception claiming callbacks to determine if an exception is thrown by one of registered
- // runtimes.
- //
- // Before a runtime goes to process Watson for an unhandled exception, it first asks Waston SxS
- // manager if a Watson report has already been submitted for the current process. If so, it
- // will not try to do Watson. If not, it checks if the unhandled exception is thrown by itself.
- // If true, it will report Watson only when Watson SxS manager allows it to do Watson.
- //
- // If the unhandled exception is not thrown by itself, it will invoke Watson SxS manager's exception
- // claiming API to determine if the unhandled exception was thrown by another runtime which is
- // responsible for reporting Watson. If true, it will not try to do Watson. If none of runtimes
- // in the process claims the ownership of the unhandled exception, it will report Watson only when
- // Watson SxS manager allows it to do Watson.
- result = DoFaultReport(pExceptionInfo, tore);
-
- // Set the event to indicate that Watson processing is completed. Other threads can continue.
- UnsafeSetEvent(g_hWatsonCompletionEvent);
- }
+
+ if (IsDebuggerPresent())
+ {
+ result = FaultReportResultDebug;
+ jitAttachRequested = FALSE;
}
switch(result)