From c252dc52e7b1e95bc7b5bc96f044652738bd9099 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Fri, 2 Oct 2015 14:55:07 +0200 Subject: [PATCH] Implement refactored Unix managed exception handling This change refactors managed exception handling so that we perform full first pass over both managed and native frames and only after we find target frame, we perform the second pass. This helps in debugging of unhandled managed exceptions since the debugger can kick in at the end of the first pass when the stack frames are still intact and it can show the context where the exception was fired. Commit migrated from https://github.com/dotnet/coreclr/commit/a723811c171a3dae340a08f24afedbfc238b7930 --- src/coreclr/src/pal/inc/pal.h | 11 ++ src/coreclr/src/vm/corhost.cpp | 2 - src/coreclr/src/vm/exceptionhandling.cpp | 269 ++++++++++++------------------- src/coreclr/src/vm/exceptionhandling.h | 26 --- src/coreclr/src/vm/exceptmacros.h | 21 --- src/coreclr/src/vm/exstatecommon.h | 11 -- src/coreclr/src/vm/frames.cpp | 13 -- src/coreclr/src/vm/frames.h | 2 +- 8 files changed, 111 insertions(+), 244 deletions(-) diff --git a/src/coreclr/src/pal/inc/pal.h b/src/coreclr/src/pal/inc/pal.h index b5cde5a..575d4a9 100644 --- a/src/coreclr/src/pal/inc/pal.h +++ b/src/coreclr/src/pal/inc/pal.h @@ -6373,6 +6373,8 @@ public: struct PAL_SEHException { +private: + const SIZE_T NoTargetFrameSp = SIZE_MAX; public: // Note that the following two are actually embedded in this heap-allocated // instance - in contrast to Win32, where the exception record would usually @@ -6381,6 +6383,8 @@ public: EXCEPTION_POINTERS ExceptionPointers; EXCEPTION_RECORD ExceptionRecord; CONTEXT ContextRecord; + // Target frame stack pointer set before the 2nd pass. + SIZE_T TargetFrameSp; PAL_SEHException(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContextRecord) { @@ -6388,6 +6392,7 @@ public: ExceptionPointers.ContextRecord = &ContextRecord; ExceptionRecord = *pExceptionRecord; ContextRecord = *pContextRecord; + TargetFrameSp = NoTargetFrameSp; } PAL_SEHException() @@ -6399,12 +6404,18 @@ public: *this = ex; } + bool IsFirstPass() + { + return (TargetFrameSp == NoTargetFrameSp); + } + PAL_SEHException& operator=(const PAL_SEHException& ex) { ExceptionPointers.ExceptionRecord = &ExceptionRecord; ExceptionPointers.ContextRecord = &ContextRecord; ExceptionRecord = ex.ExceptionRecord; ContextRecord = ex.ContextRecord; + TargetFrameSp = ex.TargetFrameSp; return *this; } diff --git a/src/coreclr/src/vm/corhost.cpp b/src/coreclr/src/vm/corhost.cpp index 161b2a1..451043fc 100644 --- a/src/coreclr/src/vm/corhost.cpp +++ b/src/coreclr/src/vm/corhost.cpp @@ -1270,7 +1270,6 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, return HOST_E_INVALIDOPERATION; } - INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP; INSTALL_UNWIND_AND_CONTINUE_HANDLER; _ASSERTE (!pThread->PreemptiveGCDisabled()); @@ -1303,7 +1302,6 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, } UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; - UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP; ErrExit: diff --git a/src/coreclr/src/vm/exceptionhandling.cpp b/src/coreclr/src/vm/exceptionhandling.cpp index e1b6925..f8b7bdb 100644 --- a/src/coreclr/src/vm/exceptionhandling.cpp +++ b/src/coreclr/src/vm/exceptionhandling.cpp @@ -3591,34 +3591,6 @@ void ExceptionTracker::PopTrackers( } } -// Save the state of the source exception tracker -void ExceptionTracker::PartialTrackerState::Save(const ExceptionTracker* pSourceTracker) -{ - m_uCatchToCallPC = pSourceTracker->m_uCatchToCallPC; - m_pClauseForCatchToken = pSourceTracker->m_pClauseForCatchToken; - m_ClauseForCatch = pSourceTracker->m_ClauseForCatch; - m_ExceptionFlags = pSourceTracker->m_ExceptionFlags; - m_sfLastUnwoundEstablisherFrame = pSourceTracker->m_sfLastUnwoundEstablisherFrame; - m_EHClauseInfo = pSourceTracker->m_EHClauseInfo; - m_EnclosingClauseInfo = pSourceTracker->m_EnclosingClauseInfo; - m_EnclosingClauseInfoForGCReporting = pSourceTracker->m_EnclosingClauseInfoForGCReporting; - m_fFixupCallerSPForGCReporting = pSourceTracker->m_fFixupCallerSPForGCReporting; -} - -// Restore the state into the target exception tracker -void ExceptionTracker::PartialTrackerState::Restore(ExceptionTracker* pTargetTracker) -{ - pTargetTracker->m_uCatchToCallPC = m_uCatchToCallPC; - pTargetTracker->m_pClauseForCatchToken = m_pClauseForCatchToken; - pTargetTracker->m_ClauseForCatch = m_ClauseForCatch; - pTargetTracker->m_ExceptionFlags = m_ExceptionFlags; - pTargetTracker->m_sfLastUnwoundEstablisherFrame = m_sfLastUnwoundEstablisherFrame; - pTargetTracker->m_EHClauseInfo = m_EHClauseInfo; - pTargetTracker->m_EnclosingClauseInfo = m_EnclosingClauseInfo; - pTargetTracker->m_EnclosingClauseInfoForGCReporting = m_EnclosingClauseInfoForGCReporting; - pTargetTracker->m_fFixupCallerSPForGCReporting = m_fFixupCallerSPForGCReporting; -} - // // static ExceptionTracker* ExceptionTracker::GetOrCreateTracker( @@ -3648,7 +3620,6 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( bool fCreateNewTracker = false; bool fIsRethrow = false; - bool fIsInterleavedHandling = false; bool fTransitionFromSecondToFirstPass = false; // Initialize the out parameter. @@ -3657,7 +3628,6 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( if (NULL != pTracker) { fTransitionFromSecondToFirstPass = fIsFirstPass && !pTracker->IsInFirstPass(); - fIsInterleavedHandling = !!pTracker->m_ExceptionFlags.IsInterleavedHandling(); CONSISTENCY_CHECK(!pTracker->m_ScannedStackRange.IsEmpty()); @@ -3670,7 +3640,7 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( fIsRethrow = true; } else - if ((pTracker->m_ptrs.ExceptionRecord != pExceptionRecord) && !fIsInterleavedHandling) + if ((pTracker->m_ptrs.ExceptionRecord != pExceptionRecord) && fIsFirstPass) { EH_LOG((LL_INFO100, ">>NEW exception (exception records do not match)\n")); fCreateNewTracker = true; @@ -3684,74 +3654,16 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( if (fTransitionFromSecondToFirstPass) { - if (fIsInterleavedHandling) + // We just transition from 2nd pass to 1st pass without knowing it. + // This means that some unmanaged frame outside of the EE catches the previous exception, + // so we should trash the current tracker and create a new one. + EH_LOG((LL_INFO100, ">>NEW exception (the previous second pass finishes at some unmanaged frame outside of the EE)\n")); { - // We just transitioned from 2nd pass to 1st pass when we handle the exception in an interleaved manner. - // In interleaved exception handling a single exception is handled in an interleaved - // series of first and second passes. We re-create the exception tracker in-place - // and carry over several members that were set when processing one of the previous frames. - EH_LOG((LL_INFO100, ">>continued processing of PREVIOUS exception (interleaved handling)\n")); - { - GCX_COOP(); - - // Remember part of the current state that needs to be transferred to - // the newly created tracker. - PartialTrackerState previousTrackerPartialState; - previousTrackerPartialState.Save(pTracker); - - // Rember the previous tracker pointer so that we can restore it - ExceptionTracker* prevTracker = pTracker->m_pPrevNestedInfo; - - // Free the tracker resources so that we can recreate a new one in-place - pTracker->ReleaseResources(); - - new (pTracker) ExceptionTracker(ControlPc, - pExceptionRecord, - pContextRecord); - - // Restore part of the tracker state that was saved before recreating the tracker - previousTrackerPartialState.Restore(pTracker); - // Reset the 'unwind has started' flag to indicate we are in the first pass again - pTracker->m_ExceptionFlags.ResetUnwindHasStarted(); - - // Restore the trackerlink to the previous exception tracker - pTracker->m_pPrevNestedInfo = prevTracker; - - OBJECTREF oThrowable = CreateThrowable(pExceptionRecord, bAsynchronousThreadStop); - - GCX_FORBID(); // we haven't protected oThrowable - - CONSISTENCY_CHECK(oThrowable != NULL); - CONSISTENCY_CHECK(NULL == pTracker->m_hThrowable); - - pThread->SafeSetThrowables(oThrowable); - - if (pTracker->CanAllocateMemory()) - { - pTracker->m_StackTraceInfo.AllocateStackTrace(); - } - - INDEBUG(oThrowable = NULL); - - _ASSERTE(pTracker->m_pLimitFrame == NULL); - pTracker->ResetLimitFrame(); - } - - *pStackTraceState = STS_Append; + GCX_COOP(); + ExceptionTracker::PopTrackers(sf, false); } - else - { - // We just transition from 2nd pass to 1st pass without knowing it. - // This means that some unmanaged frame outside of the EE catches the previous exception, - // so we should trash the current tracker and create a new one. - EH_LOG((LL_INFO100, ">>NEW exception (the previous second pass finishes at some unmanaged frame outside of the EE)\n")); - { - GCX_COOP(); - ExceptionTracker::PopTrackers(sf, false); - } - fCreateNewTracker = true; - } + fCreateNewTracker = true; } else { @@ -3992,10 +3904,7 @@ ExceptionTracker* ExceptionTracker::GetOrCreateTracker( // Lean on the safe side and just reset everything unconditionally. pTracker->FirstPassIsComplete(); - if (!fIsInterleavedHandling) - { - EEToDebuggerExceptionInterfaceWrapper::ManagedExceptionUnwindBegin(pThread); - } + EEToDebuggerExceptionInterfaceWrapper::ManagedExceptionUnwindBegin(pThread); pTracker->ResetLimitFrame(); } @@ -4445,13 +4354,12 @@ extern "C" void StartUnwindingNativeFrames(CONTEXT* context, PAL_SEHException* e // a handler using information that has been built by JIT. // // Arguments: -// exceptionRecord - an exception record that stores information about the managed exception +// ex - the PAL_SEHException representing the managed exception // unwindStartContext - the context that the unwind should start at. Either the original exception // context (when the exception didn't cross native frames) or the first managed // frame after crossing native frames. -// targetFrameSp - specifies the call frame that is the target of the unwind // -VOID UnwindManagedExceptionPass2(EXCEPTION_RECORD* exceptionRecord, CONTEXT* unwindStartContext, UINT_PTR targetFrameSp) +VOID UnwindManagedExceptionPass2(PAL_SEHException& ex, CONTEXT* unwindStartContext) { UINT_PTR controlPc; EXCEPTION_DISPOSITION disposition; @@ -4466,7 +4374,7 @@ VOID UnwindManagedExceptionPass2(EXCEPTION_RECORD* exceptionRecord, CONTEXT* unw ULONG64 stackLowAddress = (ULONG64)PAL_GetStackLimit(); // Indicate that we are performing second pass. - exceptionRecord->ExceptionFlags = EXCEPTION_UNWINDING; + ex.ExceptionRecord.ExceptionFlags = EXCEPTION_UNWINDING; currentFrameContext = unwindStartContext; callerFrameContext = &contextStorage; @@ -4504,7 +4412,7 @@ VOID UnwindManagedExceptionPass2(EXCEPTION_RECORD* exceptionRecord, CONTEXT* unw // and we did not go below that target frame. // TODO: make sure the establisher frame is properly aligned. if (!IsSpInStackLimits(establisherFrame, stackLowAddress, stackHighAddress) || - establisherFrame > targetFrameSp) + establisherFrame > ex.TargetFrameSp) { // TODO: add better error handling UNREACHABLE(); @@ -4513,14 +4421,14 @@ VOID UnwindManagedExceptionPass2(EXCEPTION_RECORD* exceptionRecord, CONTEXT* unw dispatcherContext.EstablisherFrame = establisherFrame; dispatcherContext.ContextRecord = currentFrameContext; - if (establisherFrame == targetFrameSp) + if (establisherFrame == ex.TargetFrameSp) { // We have reached the frame that will handle the exception. - exceptionRecord->ExceptionFlags |= EXCEPTION_TARGET_UNWIND; + ex.ExceptionRecord.ExceptionFlags |= EXCEPTION_TARGET_UNWIND; } // Perform unwinding of the current frame - disposition = ProcessCLRException(exceptionRecord, + disposition = ProcessCLRException(&ex.ExceptionRecord, establisherFrame, currentFrameContext, &dispatcherContext); @@ -4547,11 +4455,30 @@ VOID UnwindManagedExceptionPass2(EXCEPTION_RECORD* exceptionRecord, CONTEXT* unw if (!ExecutionManager::IsManagedCode(GetIP(currentFrameContext))) { // Return back to the UnwindManagedExceptionPass1 and let it unwind the native frames - return; + // return; + { + GCX_COOP(); + // Pop all frames that are below the block of native frames and that would be + // in the unwound part of the stack when UnwindManagedExceptionPass2 is resumed + // at the next managed frame. + + UnwindFrameChain(GetThread(), (VOID*)GetSP(currentFrameContext)); + // We are going to reclaim the stack range that was scanned by the exception tracker + // until now. We need to reset the explicit frames range so that if GC fires before + // we recreate the tracker at the first managed frame after unwinding the native + // frames, it doesn't attempt to scan the reclaimed stack range. + ExceptionTracker* pTracker = GetThread()->GetExceptionState()->GetCurrentExceptionTracker(); + pTracker->ResetUnwoundExplicitFramesRange(); + } + + //Now we need to unwind the native frames until we reach managed frames again or the exception is + //handled in the native code. + StartUnwindingNativeFrames(currentFrameContext, &ex); + UNREACHABLE(); } } while (IsSpInStackLimits(GetSP(currentFrameContext), stackLowAddress, stackHighAddress) && - (establisherFrame != targetFrameSp)); + (establisherFrame != ex.TargetFrameSp)); _ASSERTE(!"UnwindManagedExceptionPass2: Unwinding failed. Reached the end of the stack"); EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); @@ -4653,7 +4580,8 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex) { // The first pass is complete. We have found the frame that // will handle the exception. Start the second pass. - UnwindManagedExceptionPass2(&ex.ExceptionRecord, &unwindStartContext, establisherFrame); + ex.TargetFrameSp = establisherFrame; + UnwindManagedExceptionPass2(ex, &unwindStartContext); } else { @@ -4667,59 +4595,38 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex) } // Check whether we are crossing managed-to-native boundary - if (!ExecutionManager::IsManagedCode(controlPc)) + while (!ExecutionManager::IsManagedCode(controlPc)) { - // Save the exception flags of the first pass so that we can restore them after - // the partial second pass. - ExceptionFlags* currentFlags = GetThread()->GetExceptionState()->GetFlags(); - - ExceptionFlags firstPassFlags = *currentFlags; + UINT_PTR sp = GetSP(&frameContext); - // The second pass needs this flag to be reset - currentFlags->ResetUnwindingToFindResumeFrame(); - - // First we need to run the unwind second pass until we hit the current native frame. - // The targetFrameSp is set to max value to indicate that the target is not known yet. - const UINT_PTR TargetFrameSp = ULONG_PTR_MAX; - UnwindManagedExceptionPass2(&ex.ExceptionRecord, &unwindStartContext, TargetFrameSp); - - // Restore back the state of the first pass. We need to reread the current flags pointer - // since if the exception tracker changed in the second pass, the pointer would be different. - currentFlags = GetThread()->GetExceptionState()->GetFlags(); - - // Set back the UnwindHasStarted flag so that the ExceptionTracker::GetOrCreateTracker - // detects that there was a second pass and that it needs to recreate the tracker. - firstPassFlags.SetUnwindHasStarted(); - - // Tell the tracker that we are starting interleaved handling of the exception. - // The interleaved handling is used when an exception unwinding passes through - // interleaved managed and native stack frames. In that case, instead of - // performing first pass of the unwinding over all the stack range and then - // second pass over the same range, we unwind each managed / native subrange - // separately, performing both passes on a subrange before moving to the next one. - firstPassFlags.SetIsInterleavedHandling(); + BOOL success = PAL_VirtualUnwind(&frameContext, NULL); + if (!success) + { + _ASSERTE(!"Thread::VirtualUnwindToFirstManagedCallFrame: PAL_VirtualUnwind failed"); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); + } - *currentFlags = firstPassFlags; + controlPc = GetIP(&frameContext); + if (controlPc == 0) { - GCX_COOP(); - // Pop all frames that are below the block of native frames and that would be - // in the unwound part of the stack when UnwindManagedExceptionPass1 is resumed - // at the next managed frame. - UnwindFrameChain(GetThread(), (VOID*)GetSP(&frameContext)); + // This displays the managed stack in case the unwind has walked out of the stack and + // a managed exception was being unwound. + DefaultCatchHandler(NULL /*pExceptionInfo*/, NULL /*Throwable*/, TRUE /*useLastThrownObject*/, + TRUE /*isTerminating*/, FALSE /*isThreadBaseFIlter*/, FALSE /*sendAppDomainEvents*/); - // We are going to reclaim the stack range that was scanned by the exception tracker - // until now. We need to reset the explicit frames range so that if GC fires before - // we recreate the tracker at the first managed frame after unwinding the native - // frames, it doesn't attempt to scan the reclaimed stack range. - ExceptionTracker* pTracker = GetThread()->GetExceptionState()->GetCurrentExceptionTracker(); - pTracker->ResetUnwoundExplicitFramesRange(); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); } - // Now we need to unwind the native frames until we reach managed frames again or the exception is - // handled in the native code. - StartUnwindingNativeFrames(&frameContext, &ex); - UNREACHABLE(); + UINT_PTR parentSp = GetSP(&frameContext); + + NativeExceptionHolderBase* holder = NativeExceptionHolderBase::FindHolder((void*)sp, (void*)parentSp); + if ((holder != NULL) && (holder->InvokeFilter(ex) == EXCEPTION_EXECUTE_HANDLER)) + { + // Switch to pass 2 + ex.TargetFrameSp = sp; + UnwindManagedExceptionPass2(ex, &unwindStartContext); + } } } while (IsSpInStackLimits(GetSP(&frameContext), stackLowAddress, stackHighAddress)); @@ -4748,7 +4655,20 @@ VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex) { try { - UnwindManagedExceptionPass1(ex); + if (ex.IsFirstPass()) + { + UnwindManagedExceptionPass1(ex); + } + else + { + // This is a continuation of pass 2 after native frames unwinding. + // Get the managed frame to continue unwinding from. + CONTEXT frameContext; + RtlCaptureContext(&frameContext); + Thread::VirtualUnwindToFirstManagedCallFrame(&frameContext); + + UnwindManagedExceptionPass2(ex, &frameContext); + } UNREACHABLE(); } catch (PAL_SEHException& ex2) @@ -6418,26 +6338,35 @@ bool ExceptionTracker::HasFrameBeenUnwoundByAnyActiveException(CrawlFrame * pCF) fHasFrameBeenUnwound = true; break; }*/ - PTR_Frame pFrameToCheck = (PTR_Frame)csfToCheck.SP; - PTR_Frame pCurrentFrame = pInitialExplicitFrame; - + + // The pInitialExplicitFrame can be NULL on Unix right after we've unwound a sequence + // of native frames in the second pass of exception unwinding, since the pInitialExplicitFrame + // is cleared to make sure that it doesn't point to a frame that was destroyed during the + // native frames unwinding. At that point, the csfToCheck could not have been unwound, + // so we don't need to do any check. + if (pInitialExplicitFrame != NULL) { - while((pCurrentFrame != FRAME_TOP) && (pCurrentFrame != pLimitFrame)) + PTR_Frame pFrameToCheck = (PTR_Frame)csfToCheck.SP; + PTR_Frame pCurrentFrame = pInitialExplicitFrame; + { - if (pCurrentFrame == pFrameToCheck) + while((pCurrentFrame != FRAME_TOP) && (pCurrentFrame != pLimitFrame)) { - fHasFrameBeenUnwound = true; - break; + if (pCurrentFrame == pFrameToCheck) + { + fHasFrameBeenUnwound = true; + break; + } + + pCurrentFrame = pCurrentFrame->PtrNextFrame(); } + } - pCurrentFrame = pCurrentFrame->PtrNextFrame(); + if (fHasFrameBeenUnwound == true) + { + break; } } - - if (fHasFrameBeenUnwound == true) - { - break; - } } } diff --git a/src/coreclr/src/vm/exceptionhandling.h b/src/coreclr/src/vm/exceptionhandling.h index f1b20ea..ceb806e 100644 --- a/src/coreclr/src/vm/exceptionhandling.h +++ b/src/coreclr/src/vm/exceptionhandling.h @@ -683,32 +683,6 @@ private: ; bool m_fEnclosingClauseIsFunclet; }; - // This class saves partial state of an exception tracker that needs to - // be preserved when transitioning from the 2nd to 1st pass during the - // interleaved exception handling before processing next segment of - // managed stack frames. - // The exception tracker is recreated during such transition and - // only a subset of the exception tracker state defined by this class - // is propagated to the new tracker instance. - class PartialTrackerState - { - UINT_PTR m_uCatchToCallPC; - PTR_EXCEPTION_CLAUSE_TOKEN m_pClauseForCatchToken; - EE_ILEXCEPTION_CLAUSE m_ClauseForCatch; - ExceptionFlags m_ExceptionFlags; - StackFrame m_sfLastUnwoundEstablisherFrame; - EHClauseInfo m_EHClauseInfo; - EnclosingClauseInfo m_EnclosingClauseInfo; - EnclosingClauseInfo m_EnclosingClauseInfoForGCReporting; - bool m_fFixupCallerSPForGCReporting; - - public: - // Save the state of the source exception tracker - void Save(const ExceptionTracker* pSourceTracker); - // Restore the state into the target exception tracker - void Restore(ExceptionTracker* pTargetTracker); - }; - PTR_ExceptionTracker m_pPrevNestedInfo; Thread* m_pThread; // this is used as an IsValid/IsFree field -- if it's NULL, the allocator can // reuse its memory, if it's non-NULL, it better be a valid thread pointer diff --git a/src/coreclr/src/vm/exceptmacros.h b/src/coreclr/src/vm/exceptmacros.h index 74de307..3c426fd 100644 --- a/src/coreclr/src/vm/exceptmacros.h +++ b/src/coreclr/src/vm/exceptmacros.h @@ -339,31 +339,10 @@ VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex); DispatchManagedException(exCopy); \ } -// Install trap that catches unhandled managed exception and dumps its stack -#define INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP \ - try { - -// Uninstall trap that catches unhandled managed exception and dumps its stack -#define UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP \ - } \ - catch (PAL_SEHException& ex) \ - { \ - DefaultCatchHandler( \ - NULL /*pExceptionInfo*/, \ - NULL /*Throwable*/, \ - TRUE /*useLastThrownObject*/, \ - TRUE /*isTerminating*/, \ - FALSE /*isThreadBaseFIlter*/, \ - FALSE /*sendAppDomainEvents*/); \ - EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); \ - } - #else #define INSTALL_MANAGED_EXCEPTION_DISPATCHER #define UNINSTALL_MANAGED_EXCEPTION_DISPATCHER -#define INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP -#define UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP #endif // FEATURE_PAL diff --git a/src/coreclr/src/vm/exstatecommon.h b/src/coreclr/src/vm/exstatecommon.h index 7b1f19b..7dbfc12 100644 --- a/src/coreclr/src/vm/exstatecommon.h +++ b/src/coreclr/src/vm/exstatecommon.h @@ -337,14 +337,6 @@ public: void SetIsRethrown() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_IsRethrown; } void ResetIsRethrown() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_IsRethrown; } -#ifdef FEATURE_PAL - BOOL IsInterleavedHandling() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_IsInterleavedHandling; } - void SetIsInterleavedHandling() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_IsInterleavedHandling; } - void ResetIsInterleavedHandling() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_IsInterleavedHandling; } -#else // FEATURE_PAL - BOOL IsInterleavedHandling() { return FALSE; } -#endif // FEATURE_PAL - BOOL UnwindHasStarted() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_UnwindHasStarted; } void SetUnwindHasStarted() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_UnwindHasStarted; } void ResetUnwindHasStarted() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_UnwindHasStarted; } @@ -425,10 +417,7 @@ private: Ex_GotWatsonBucketInfo = 0x00004000, - Ex_IsInterleavedHandling = 0x00008000 - #if defined(WIN64EXCEPTIONS) && defined(_DEBUG) - , Ex_FlagsAreReadOnly = 0x80000000 #endif // defined(WIN64EXCEPTIONS) && defined(_DEBUG) diff --git a/src/coreclr/src/vm/frames.cpp b/src/coreclr/src/vm/frames.cpp index 1e3e9e0..0037ed1 100644 --- a/src/coreclr/src/vm/frames.cpp +++ b/src/coreclr/src/vm/frames.cpp @@ -479,19 +479,6 @@ VOID Frame::Pop(Thread *pThread) pThread->SetFrame(m_Next); } -#ifdef FEATURE_PAL -Frame::~Frame() -{ - // When the frame is destroyed, make sure it is no longer in the - // frame chain managed by the Thread. - Thread* pThread = GetThread(); - if (pThread != NULL && pThread->GetFrame() == this) - { - Pop(pThread); - } -} -#endif // FEATURE_PAL - //----------------------------------------------------------------------- #endif // #ifndef DACCESS_COMPILE //--------------------------------------------------------------- diff --git a/src/coreclr/src/vm/frames.h b/src/coreclr/src/vm/frames.h index dcaa440..33b88f7 100644 --- a/src/coreclr/src/vm/frames.h +++ b/src/coreclr/src/vm/frames.h @@ -419,7 +419,7 @@ class Frame : public FrameBase public: #if defined(FEATURE_PAL) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) - virtual ~Frame(); + virtual ~Frame() {} #endif // FEATURE_PAL && !DACCESS_COMPILE && !CROSSGEN_COMPILE //------------------------------------------------------------------------ -- 2.7.4