summaryrefslogtreecommitdiff
path: root/src/vm/exceptionhandling.h
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2015-03-30 12:06:12 +0200
committerJan Vorlicek <janvorli@microsoft.com>2015-03-30 12:06:12 +0200
commit73a8ac6fdbf12eff1102adcac62750c209789589 (patch)
tree0307c8cf9edf6fee6677f6661755d380987556f6 /src/vm/exceptionhandling.h
parent898cdcf05ae334252b354a1f5bae9e26be1912ec (diff)
downloadcoreclr-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.h33
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;