@@ -1293,6 +1293,16 @@ void RemoveGcCoverageInterrupt(TADDR instrPtr, BYTE * savedInstrPtr, GCCoverageI
12931293    FlushInstructionCache (GetCurrentProcess (), (LPCVOID)instrPtr, 4 );
12941294}
12951295
1296+ //  A managed thread (T) can race with the GC as follows:
1297+ //  1) Current thread T is in preemptive mode, GC happens, starts scanning T's stack.
1298+ //  2) The Jitted code puts thread T to cooperative mode, as part of PInvoke epilog.
1299+ //  3) Jitted code checks g_TrapReturningThreads, calls CORINFO_HELP_STOP_FOR_GC()
1300+ //  4) If any of the code that does #3 is interruptible, we may hit GCStress trap and start
1301+ //     another round of GCStress while in Cooperative mode.
1302+ //  5) Now, thread T can modify the stack (ex: RedirectionFrame setup) while the GC thread is scanning it.
1303+ // 
1304+ //  This race is now mitigated below. Where we won't initiate a stress mode GC
1305+ //  for a thread in cooperative mode with an active ICF, if g_TrapReturningThreads is true.
12961306BOOL OnGcCoverageInterrupt (PCONTEXT regs)
12971307{
12981308    PCODE controlPc = GetIP (regs);
@@ -1324,12 +1334,22 @@ BOOL OnGcCoverageInterrupt(PCONTEXT regs)
13241334    }
13251335
13261336    //  The thread is in preemptive mode. Normally, it should not be able to trigger GC.
1337+     //  Besides the GC may be already happening and scanning our stack.
13271338    if  (!pThread->PreemptiveGCDisabled ())
13281339    {
13291340        RemoveGcCoverageInterrupt (instrPtr, savedInstrPtr, gcCover, offset);
13301341        return  TRUE ;
13311342    }
13321343
1344+     //  If we're supposed to stop for GC,
1345+     //  and there's an active ICF, don't initiate a stress GC.
1346+     Frame* pFrame = pThread->GetFrame ();
1347+     if  (g_TrapReturningThreads && InlinedCallFrame::FrameHasActiveCall (pFrame))
1348+     {
1349+         RemoveGcCoverageInterrupt (instrPtr, savedInstrPtr, gcCover, offset);
1350+         return  TRUE ;
1351+     }
1352+ 
13331353#ifdef  _DEBUG
13341354    if  (g_pConfig->SkipGCCoverage (pMD->GetModule ()->GetSimpleName ()))
13351355    {
@@ -1338,7 +1358,7 @@ BOOL OnGcCoverageInterrupt(PCONTEXT regs)
13381358    }
13391359#endif 
13401360
1341- #if  defined( USE_REDIRECT_FOR_GCSTRESS) && !defined(TARGET_UNIX) 
1361+ #ifdef   USE_REDIRECT_FOR_GCSTRESS
13421362    //  If we're unable to redirect, then we simply won't test GC at this location.
13431363    if  (Thread::UseRedirectForGcStress ())
13441364    {
0 commit comments