diff options
author | Jan Kotas <jkotas@microsoft.com> | 2015-04-27 07:57:57 -0700 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2015-04-27 07:57:57 -0700 |
commit | 05e2aa8577806dba3ee794555e2964be4504cd2d (patch) | |
tree | 59f2ac8412809929c42583c83a22a2f2aacef6a3 | |
parent | 1883cd4a5ee07d8f5ae945ae6037d06d751c74fc (diff) | |
parent | ec2354ec577b1fbe591018aa9fff6a769e3d2df4 (diff) | |
download | coreclr-05e2aa8577806dba3ee794555e2964be4504cd2d.tar.gz coreclr-05e2aa8577806dba3ee794555e2964be4504cd2d.tar.bz2 coreclr-05e2aa8577806dba3ee794555e2964be4504cd2d.zip |
Merge pull request #829 from janvorli/fix-secondary-thread-gc
Fix GC of other thread during native frames unwinding
-rw-r--r-- | src/vm/exceptionhandling.cpp | 24 | ||||
-rw-r--r-- | src/vm/exceptionhandling.h | 7 |
2 files changed, 25 insertions, 6 deletions
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index ed5e162e9a..5f87ccf093 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -4589,10 +4589,20 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex) *currentFlags = firstPassFlags; - // 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); + { + GCX_COOP(); + // 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); + + // We are going to reclaim the stack range that was scanned by the exception tracker + // until now. We need to reset the explicit frames range so that if GC fires before + // we recreate the tracker at the first managed frame after unwinding the native + // frames, it doesn't attempt to scan the reclaimed stack range. + ExceptionTracker* pTracker = GetThread()->GetExceptionState()->GetCurrentExceptionTracker(); + pTracker->ResetUnwoundExplicitFramesRange(); + } // Now we need to unwind the native frames until we reach managed frames again or the exception is // handled in the native code. @@ -4961,8 +4971,10 @@ VOID PALAPI HandleHardwareException(PAL_SEHException* ex) #if defined(WIN64EXCEPTIONS) *((&fef)->GetGSCookiePtr()) = GetProcessGSCookie(); #endif // WIN64EXCEPTIONS - GCX_COOP(); - fef.InitAndLink(&ex->ContextRecord); + { + GCX_COOP(); // Must be cooperative to modify frame chain. + fef.InitAndLink(&ex->ContextRecord); + } #ifdef _AMD64_ // It is possible that an overflow was mapped to a divide-by-zero exception. diff --git a/src/vm/exceptionhandling.h b/src/vm/exceptionhandling.h index c8581e3b95..72db3576a3 100644 --- a/src/vm/exceptionhandling.h +++ b/src/vm/exceptionhandling.h @@ -298,6 +298,13 @@ public: return m_pInitialExplicitFrame; } + // Reset the range of explicit frames that covers already unwound frames. + void ResetUnwoundExplicitFramesRange() + { + m_pInitialExplicitFrame = NULL; + m_pLimitFrame = NULL; + } + // Determines if we have unwound to the specified parent method frame. // Currently this is only used for funclet skipping. static bool IsUnwoundToTargetParentFrame(CrawlFrame * pCF, StackFrame sfParent); |