diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2015-03-30 12:06:12 +0200 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2015-03-30 12:06:12 +0200 |
commit | 73a8ac6fdbf12eff1102adcac62750c209789589 (patch) | |
tree | 0307c8cf9edf6fee6677f6661755d380987556f6 /src/vm/exceptionhandling.h | |
parent | 898cdcf05ae334252b354a1f5bae9e26be1912ec (diff) | |
download | coreclr-73a8ac6fdbf12eff1102adcac62750c209789589.tar.gz coreclr-73a8ac6fdbf12eff1102adcac62750c209789589.tar.bz2 coreclr-73a8ac6fdbf12eff1102adcac62750c209789589.zip |
Fix GC exception related issue
This change fixes a problem that has occured when GC was called from
an exception handler during split exception handling. The problem
manifestated itself as a crash in the HasFrameBeenUnwoundByAnyActiveException
function due to the pInitialExplicitFrame being NULL.
The cause of this issue was caused by a combination of two issues.
First, the m_ScannedStackRange was not reset in the partial 2nd pass to
the state at the beginning of the corresponding partial 1st pass.
And second, the 'unwind has started' flag was not reset after
restoring exception flags in the new exception tracker after switching
from the 2nd back to the 1st pass during the split exception handling.
There was one additional issue, several additional members of the exception
tracker needed to be propagated to the new tracker. These members are
needed by the HasFrameBeenUnwoundByAnyActiveException function.
Since the number of state members that are propagated from the old to the
new exception tracker has grown, I've refactored the code to keep those
in a separate class.
Diffstat (limited to 'src/vm/exceptionhandling.h')
-rw-r--r-- | src/vm/exceptionhandling.h | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/vm/exceptionhandling.h b/src/vm/exceptionhandling.h index 5b2568aadc..9362fa4a65 100644 --- a/src/vm/exceptionhandling.h +++ b/src/vm/exceptionhandling.h @@ -660,11 +660,44 @@ 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 + { + StackFrame m_sfResumeStackFrame; + StackRange m_ScannedStackRange; + 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; + + 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 StackRange m_ScannedStackRange; + // Range used to initialize the m_ScannedStackRange at start of the 2nd pass. + // This is: + // 1) null range for non-interleaved exception handling and the very first + // 2nd pass of the interleaved handling and + // 2) non-null for the other 2nd passes of the interleaved handling. + StackRange m_secondPassInitialScannedStackRange; DAC_EXCEPTION_POINTERS m_ptrs; OBJECTHANDLE m_hThrowable; StackTraceInfo m_StackTraceInfo; |