From a09046a6409f61e40958404bcc82abf81e12b73e Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 5 Jan 2016 11:09:53 +0100 Subject: [PATCH] Fix exception tracker popping in a corner case This change fixes exception tracker popping in case a managed exception is handled in the CoreCLR native code. The current exception tracker has an empty scanned stack range in that case and the existing code in the ExceptionTracker::PopTrackers was skipping the popping in such case, considering it a case when an exception happened while the exception tracker was being setup. Adding check that the tracker is in the first pass to that condition fixes the problem, since when the tracker is in the second pass, it cannot be the case in which the PopTrackers wanted to skip the popping. The tracker is then popped correctly in the code below. I have also reverted a fix for the exception from filter which was conflicting with this fix and this fix fixes the problem of the exception from filter too. --- src/vm/exceptionhandling.cpp | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index 38e8836..a4d90d7 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -2953,33 +2953,6 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame( COMPrincipal::CLR_ImpersonateLoggedOnUser(m_hImpersonationToken); impersonating = FALSE; } -#else // !FEATURE_PAL - { - // Since we have caught the exception from the filter here in the native code, - // the exception tracker is still in the cleaned up state that we've created - // before starting native frames unwind in the UnwindManagedExceptionPass2. - // We can remove the tracker since we don't need any of the information that - // it contains anymore. - - // To be safe to pop the tracker, we need to be in cooperative mode to make sure - // the GC won't get triggered in the middle of the tracker removal. - GCX_COOP(); - ExceptionTracker* pTrackerToFree = pThread->GetExceptionState()->m_pCurrentTracker; - CONSISTENCY_CHECK(pTrackerToFree->IsValid()); - _ASSERTE(pTrackerToFree->m_ScannedStackRange.IsEmpty()); - - EH_LOG((LL_INFO100, "Unlinking ExceptionTracker object 0x%p, thread = 0x%p\n", pTrackerToFree, pTrackerToFree->m_pThread)); - - // free managed tracker resources causing notification -- do this before unlinking the tracker - // this is necessary so that we know an exception is still in flight while we give the notification - FreeTrackerMemory(pTrackerToFree, memManaged); - - // unlink the tracker from the thread - pThread->GetExceptionState()->m_pCurrentTracker = pTrackerToFree->m_pPrevNestedInfo; - - // free unmanaged tracker resources - FreeTrackerMemory(pTrackerToFree, memUnmanaged); - } #endif // !FEATURE_PAL // Sync managed exception state, for the managed thread, based upon the active exception tracker. @@ -3522,12 +3495,12 @@ void ExceptionTracker::PopTrackers( // This method is a no-op when there is no managed Thread object. We detect such a case and short circuit out in ExceptionTrackers::PopTrackers. // If this ever changes, then please revisit that method and fix it up appropriately. - // If this tracker does not have valid stack ranges, + // If this tracker does not have valid stack ranges and it is in the first pass, // then we came here likely when the tracker was being setup // and an exception took place. // // In such a case, we will not pop off the tracker - if (pTracker && pTracker->m_ScannedStackRange.IsEmpty()) + if (pTracker && pTracker->m_ScannedStackRange.IsEmpty() && pTracker->IsInFirstPass()) { // skip any others with empty ranges... do -- 2.7.4