summaryrefslogtreecommitdiff
path: root/src/vm/i386
diff options
context:
space:
mode:
authorGaurav Khanna <gkhanna@microsoft.com>2015-09-16 11:45:06 -0700
committerGaurav Khanna <gkhanna@microsoft.com>2015-09-16 11:45:06 -0700
commit14de7d30063c2955523c1ff2ccb48e339977742b (patch)
tree57642fc0f77be01af88e595dae9360ecc9660f78 /src/vm/i386
parent8cad40bbcf4c404c518c1f202a0f93cf71c866c6 (diff)
downloadcoreclr-14de7d30063c2955523c1ff2ccb48e339977742b.tar.gz
coreclr-14de7d30063c2955523c1ff2ccb48e339977742b.tar.bz2
coreclr-14de7d30063c2955523c1ff2ccb48e339977742b.zip
Fix for GH issue 410 - https://github.com/dotnet/coreclr/issues/410
Whenever a managed exception is thrown, the details about the thrown exception are also saved off the managed thread object (as LastThrownObject). The VM also has an exception tracker that tracks its dispatch across the managed frames and incase of nested exceptions, the trackers are collapsed correctly, when the nested exception is handled, and last thrown object is updated correctly. The VM works on the premise that the LastThrownObject is updated correctly. Incase of this bug, a method (M1)is invoked via Reflection and has an exception E1. During exception dispatch for E1, an IL filter is invoked that, in turn, has an exception (E2) that remains unhandled. While this is swallowed by the VM (as expected), the LastThrownObject is not updated to reflect the active exception to be E1. Thus, when the dispatch for original exception E1 completes and no managed handler is found, the exception is caught by Reflection subsystem that extracts the thrown exception using the GET_THROWABLE macro that uses the LastThrownObject to determine the thrown exception. Since the LTO was not updated, it still reflects E2. The fix is to update the managed exception state, if the filter has an unhandled exception, similar to how we do when a managed catch block successfully handles the exception. I have refactored the code to make the semantic cleaner. [tfs-changeset: 1525835]
Diffstat (limited to 'src/vm/i386')
-rw-r--r--src/vm/i386/excepx86.cpp28
1 files changed, 12 insertions, 16 deletions
diff --git a/src/vm/i386/excepx86.cpp b/src/vm/i386/excepx86.cpp
index 6bf26a4790..7de7b43e0d 100644
--- a/src/vm/i386/excepx86.cpp
+++ b/src/vm/i386/excepx86.cpp
@@ -1890,18 +1890,11 @@ NOINLINE LPVOID COMPlusEndCatchWorker(Thread * pThread)
pExInfo->UnwindExInfo(esp);
- // This will set the last thrown to be either null if we have handled all the exceptions in the nested chain or
- // to whatever the current exception is.
+ // Prepare to sync managed exception state
//
// In a case when we're nested inside another catch block, the domain in which we're executing may not be the
// same as the one the domain of the throwable that was just made the current throwable above. Therefore, we
// make a special effort to preserve the domain of the throwable as we update the the last thrown object.
- pThread->SafeUpdateLastThrownObject();
-
-#ifdef FEATURE_CORRUPTING_EXCEPTIONS
- // Since the catch clause has successfully executed and we are exiting it, reset the corruption severity
- // in the ThreadExceptionState for the last active exception. This will ensure that when the next exception
- // gets thrown/raised, EH tracker wont pick up an invalid value.
//
// This function (COMPlusEndCatch) can also be called by the in-proc debugger helper thread on x86 when
// an attempt to SetIP takes place to set IP outside the catch clause. In such a case, managed thread object
@@ -1910,13 +1903,10 @@ NOINLINE LPVOID COMPlusEndCatchWorker(Thread * pThread)
// This behaviour (of debugger doing SetIP) is not allowed on 64bit since the catch clauses are implemented
// as a seperate funclet and it's just not allowed to set the IP across EH scopes, such as from inside a catch
// clause to outside of the catch clause.
-
bool fIsDebuggerHelperThread = (g_pDebugInterface == NULL) ? false : g_pDebugInterface->ThisIsHelperThread();
- if (fIsDebuggerHelperThread == false)
- {
- CEHelper::ResetLastActiveCorruptionSeverityPostCatchHandler();
- }
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
+
+ // Sync managed exception state, for the managed thread, based upon any active exception tracker
+ pThread->SyncManagedExceptionState(fIsDebuggerHelperThread);
LOG((LF_EH, LL_INFO1000, "COMPlusPEndCatch: esp=%p\n", esp));
@@ -2241,7 +2231,8 @@ int COMPlusThrowCallbackHelper(IJitManager *pJitManager,
ThrowCallbackType* pData,
EE_ILEXCEPTION_CLAUSE *EHClausePtr,
DWORD nestingLevel,
- OBJECTREF throwable
+ OBJECTREF throwable,
+ Thread *pThread
)
{
CONTRACTL
@@ -2292,6 +2283,10 @@ int COMPlusThrowCallbackHelper(IJitManager *pJitManager,
impersonating = FALSE;
}
+ // We had an exception in filter invocation that remained unhandled.
+ // Sync managed exception state, for the managed thread, based upon the active exception tracker.
+ pThread->SyncManagedExceptionState(false);
+
//
// Swallow exception. Treat as exception continue search.
//
@@ -2702,7 +2697,8 @@ StackWalkAction COMPlusThrowCallback( // SWA value
pData,
&EHClause,
nestingLevel,
- throwable);
+ throwable,
+ pThread);
pExInfo->m_EHClauseInfo.SetManagedCodeEntered(FALSE);