summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2015-04-09 20:56:37 +0200
committerJan Vorlicek <janvorli@microsoft.com>2015-04-10 11:00:43 +0200
commit1ba226bd76e1d1c4ff2ed36a8c90cc725ed3b337 (patch)
tree095a11bfc061d2e4cb0dcdcd0fab7877a99d7873 /src/vm
parenta64519b1f982ad4179f3973e43af2389b700f3bd (diff)
downloadcoreclr-1ba226bd76e1d1c4ff2ed36a8c90cc725ed3b337.tar.gz
coreclr-1ba226bd76e1d1c4ff2ed36a8c90cc725ed3b337.tar.bz2
coreclr-1ba226bd76e1d1c4ff2ed36a8c90cc725ed3b337.zip
Fix one more exception handling issue
This change fixes exception handling issue that resulted in a finally block being invoked multiple times in case of a rethrown exception in some specific cases. The problem was caused by the ExceptionTracker::StackRange::CombineWith that was not handling correctly the case when the current stack range was empty. It was copying only the upper limit from the previous range and leaving the lower limit at the default (max) value. This case happens in the interleaved exception handling when processing the first managed frame after a block of native frames was unwound. There is one additional fix in the UnwindManagedExceptionPass1 where we were popping one frame from the thread's frame list before performing the native frames unwind. This was not correct since in some cases, there can be more frames that need to be removed.
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/exceptionhandling.cpp17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp
index 399631877f..6886f4c0f1 100644
--- a/src/vm/exceptionhandling.cpp
+++ b/src/vm/exceptionhandling.cpp
@@ -4587,10 +4587,10 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex)
*currentFlags = firstPassFlags;
- // Pop the last managed frame so that when the native frames are unwound and
- // the UnwindManagedExceptionPass1 is resumed at the next managed frame, that
- // managed frame is the current one set in the thread object.
- GetThread()->GetFrame()->Pop();
+ // 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*)frameContext.Rsp);
// Now we need to unwind the native frames until we reach managed frames again or the exception is
// handled in the native code.
@@ -5527,6 +5527,15 @@ void ExceptionTracker::StackRange::CombineWith(StackFrame sfCurrent, StackRange*
}
else
{
+#ifdef FEATURE_PAL
+ // When the current range is empty, copy the low bound too. Otherwise a degenerate range would get
+ // created and tests for stack frame in the stack range would always fail.
+ // TODO: Check if we could enable it for non-PAL as well.
+ if (IsEmpty())
+ {
+ m_sfLowBound = pPreviousRange->m_sfLowBound;
+ }
+#endif // FEATURE_PAL
m_sfHighBound = pPreviousRange->m_sfHighBound;
}
}