Runtime: Assert failure(PID 2292 [0x000008f4], Thread: 2312 [0x0908]): !g_pConfig->fAssertOnFailFast() || (m_Next == FRAME_TOP) || (*m_Next->GetGSCookiePtr() == GetProcessGSCookie())

Created on 16 Mar 2020  路  33Comments  路  Source: dotnet/runtime

Job:
runtime-coreclr gcstress0x3-gcstress0xc:20200315.1
Error message:

Assert failure(PID 2292 [0x000008f4], Thread: 2312 [0x0908]): !g_pConfig->fAssertOnFailFast() || (m_Next == FRAME_TOP) || (*m_Next->GetGSCookiePtr() == GetProcessGSCookie())

CORECLR! Frame::Push + 0x1A9 (0x00007ff956303ad9)
CORECLR! Frame::Push + 0xDE (0x00007ff956303c0a)
CORECLR! Thread::RedirectedHandledJITCase + 0x1AD (0x00007ff9561b7a05)
CORECLR! RedirectedHandledJITCaseForGCStress_Stub + 0x26 (0x00007ff956615a06)
<no module>! <no symbol> + 0x0 (0x00007ff8f72c00f5)
<no module>! <no symbol> + 0x0 (0x00007ff8f6e0f518)
<no module>! <no symbol> + 0x0 (0x0000000000003039)
<no module>! <no symbol> + 0x0 (0x000000000000018c)
<no module>! <no symbol> + 0x0 (0xffffffffffffffff)
<no module>! <no symbol> + 0x0 (0x9abcdef012345678)
File: F:\workspace\_work\1\s\src\coreclr\src\vm\frames.cpp Line: 417
Image: C:\h\w\B366092E\p\CoreRun.exe

Return code: 1\r\nRaw output file: C:\h\w\B366092E\w\AA26098B\e\Interop\NativeCallable\Reports\Interop.NativeCallable\NativeCallableTest\NativeCallableTest.output.txt
Raw output:
BEGIN EXECUTION
"C:\h\w\B366092E\p\corerun.exe" NativeCallableTest.dll
Running TestNativeCallableValid...
Running TestNativeCallableValid_OnNewNativeThread...
Running TestNativeCallableValid_PrepareMethod...
Running NegativeTest_NonStaticMethod...
Running NegativeTest_ViaDelegate...
Running NegativeTest_NonBlittable...
Running NegativeTest_NonInstantiatedGenericArguments...
Running NegativeTest_InstantiatedGenericArguments...
Running NegativeTest_FromInstantiatedGenericClass...
Running TestNativeCallableViaUnmanagedCalli...
Running TestNativeCallableValid_ThrowException...
Expected: 100
Actual: -1073740286
END EXECUTION - FAILED
FAILED
Test Harness Exitcode is : 1
To run the test:
> set CORE_ROOT=C:\h\w\B366092E\p
> C:\h\w\B366092E\w\AA26098B\e\Interop\NativeCallable\NativeCallableTest\NativeCallableTest.cmd
Expected: True
Actual: False

Stack trace:
at Interop_NativeCallable._NativeCallableTest_NativeCallableTest_._NativeCallableTest_NativeCallableTest_cmd() in F:\workspace\_work\1\s\artifacts\tests\coreclr\Windows_NT.x64.Checked\TestWrappers\Interop.NativeCallable\Interop.NativeCallable.XUnitWrapper.cs:line 140
Details:
https://dev.azure.com/dnceng/public/_build/results?buildId=560162&view=ms.vss-test-web.build-test-results-tab&runId=17645012&resultId=101118&paneView=debug

GCStress arch-x64 area-Interop-coreclr os-windows

All 33 comments

@jkotas or @janvorli Any suggestions here on how to address this for Windows would be helpful. I have a fix for #33612, but this one seems related to the exception handling side of things that I am less knowledgable about how to mitigate.

This is easy to reproduce locally. Looks like an issue with TestNativeCallableValid_ThrowException() test.

https://github.com/dotnet/runtime/blob/a1af0f2ad6cf51107a636dbe280cf939abd46b34/src/coreclr/tests/src/Interop/NativeCallable/NativeCallableTest.cs#L210-L255

Bah. I think this is my bad. @jkotas If I recall a conversation about exceptions and the NativeCallableAttribute, the expectation here is that they don't mix at all and we shouldn't even be trying to validate them right? If so I will disable those tests since I added them just to have a set of scenarios I could validate fail. Looks like on GCStress they really don't work due to the stack walking logic in https://github.com/dotnet/runtime/blob/4ceccbba7455349dffc91745d78814c5c8dc939e/src/coreclr/src/vm/exceptionhandling.cpp#L6392

On Windows, the managed exception should get converted to SEH exception on the NativeCallable boundary.
On Unix, the managed exception should become unhanded on the NativeCallable boundary.

I think we are missing "unwind and continue" on the NativeCallable boundary. @janvorli Do you have thoughts about the best way to fix that?

I'll take a look. It seems that we need to do what the personality routine at the UMThunkStub was doing when unwinding from the managed frame of a native callable function. That is what the UMThunkUnwindFrameChainHandler was doing. It seems we could do that somewhere down the ProcessCLRException call chain, but I need to figure out the exact details.

I am actually getting a different assert when running with COMPlus_GCStress=C. It happens because the GetThread() returns NULL. So we are missing a runtime thread data structure creation when we enter the managed function on a foreign thread. I would expect the JIT_ReversePInvokeEnter to do that.

  # Child-SP          RetAddr           Call Site
00 (Inline Function) --------`-------- KERNELBASE!DebugBreak [minkernel\kernelbase\debug.c @ 143] 
01 00000050`7487da68 00007ffc`18f5edac KERNELBASE!wil::details::DebugBreak+0x2 [internal\sdk\inc\wil\opensource\wil\result_macros.h @ 1684] 
02 00000050`7487da70 00007ffc`18ff6d2a CoreCLR!DbgAssertDialog+0x34c [F:\git\runtime3\src\coreclr\src\utilcode\debug.cpp @ 713] 
03 00000050`7487dcb0 00007ffc`18ff235b CoreCLR!GCHolderBase::EnterInternalCoop+0x5a [F:\git\runtime3\src\coreclr\src\vm\threads.h @ 5448] 
04 00000050`7487dcf0 00007ffc`191b47c9 CoreCLR!GCCoop::GCCoop+0x6b [F:\git\runtime3\src\coreclr\src\vm\threads.h @ 5580] 
05 00000050`7487dd40 00007ffc`b2a4121f CoreCLR!ProcessCLRException+0x389 [F:\git\runtime3\src\coreclr\src\vm\exceptionhandling.cpp @ 925] 
06 00000050`7487e800 00007ffc`b2a0a289 ntdll!RtlpExecuteHandlerForException+0xf [minkernel\ntos\rtl\amd64\xcptmisc.asm @ 132] 
07 00000050`7487e830 00007ffc`b2a3fe8e ntdll!RtlDispatchException+0x219 [minkernel\ntos\rtl\amd64\exdsptch.c @ 693] 
08 00000050`7487ef40 00007ffb`ba8c530b ntdll!KiUserExceptionDispatch+0x2e [minkernel\ntos\rtl\amd64\trampoln.asm @ 749] 
09 00000050`7487fd10 00007ffc`1fda0beb NativeCallableTest!Program.ManagedCallback_Prepared(Int32)+0x1b*** WARNING: Unable to verify checksum for F:\git\runtime3\artifacts\tests\coreclr\Windows_NT.x64.Debug\Interop\NativeCallable\NativeCallableTest\NativeCallableTest.dll

0a 00000050`7487fd60 00007ffc`1fda0983 NativeCallableDll!CallManagedProc+0x3b [F:\git\runtime3\src\coreclr\tests\src\Interop\NativeCallable\NativeCallableDll.cpp @ 14] 
0b 00000050`7487fda0 00007ffc`1fda0487 NativeCallableDll!`anonymous namespace'::ProxyCall+0x33 [F:\git\runtime3\src\coreclr\tests\src\Interop\NativeCallable\NativeCallableDll.cpp @ 27] 
0c 00000050`7487fdd0 00007ffc`1fda06cc NativeCallableDll!std::_Invoker_functor::_Call<void (__cdecl*)(`anonymous namespace'::ProxyCallContext *),A0x81f7f9a3::ProxyCallContext *>+0x57 [C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.26.28619\include\type_traits @ 1610] 
0d 00000050`7487fe10 00007ffc`1fda0526 NativeCallableDll!std::invoke<void (__cdecl*)(`anonymous namespace'::ProxyCallContext *),A0x81f7f9a3::ProxyCallContext *>+0x4c [C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.26.28619\include\type_traits @ 1610] 
0e 00000050`7487fe50 00007ffc`1fe4950c NativeCallableDll!std::thread::_Invoke<std::tuple<void (__cdecl*)(`anonymous namespace'::ProxyCallContext *),A0x81f7f9a3::ProxyCallContext *>,0,1>+0x76 [C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.26.28619\include\thread @ 44] 
0f 00000050`7487feb0 00007ffc`b28b7bd4 NativeCallableDll!thread_start<unsigned int (__cdecl*)(void *),1>+0x9c  
10 00000050`7487ff10 00007ffc`b2a0ced1 KERNEL32!BaseThreadInitThunk+0x14  
11 00000050`7487ff40 00000000`00000000 ntdll!RtlUserThreadStart+0x21  

And looking into it more, I can see the cause. The Program.ManagedCallback_Prepared(Int32) doesn't have a call to the JIT_ReversePInvokeEnter:

0:009> !u 00007ffb`ba8d530b
Normal JIT generated code
Program.ManagedCallback_Prepared(Int32)
ilAddr is 000001C6E110234C pImport is 00000150FE19AF90
Begin 00007FFBBA8D52F0, size 67

F:\git\runtime3\src\coreclr\tests\src\Interop\NativeCallable\NativeCallableTest.cs @ 159:
00007ffb`ba8d52f0 55              push    rbp
00007ffb`ba8d52f1 4883ec40        sub     rsp,40h
00007ffb`ba8d52f5 488d6c2440      lea     rbp,[rsp+40h]
00007ffb`ba8d52fa c5d857e4        vxorps  xmm4,xmm4,xmm4
00007ffb`ba8d52fe c5f97f65e0      vmovdqa xmmword ptr [rbp-20h],xmm4
00007ffb`ba8d5303 c5f97f65f0      vmovdqa xmmword ptr [rbp-10h],xmm4
00007ffb`ba8d5308 894d10          mov     dword ptr [rbp+10h],ecx
>>> 00007ffb`ba8d530b 488d4de0        lea     rcx,[rbp-20h]
00007ffb`ba8d530f e8cca49a5e      call    CoreCLR!ProfToEEInterfaceImpl::GetCodeInfo4+0x43c (00007ffc`196601ec) (gcstress) (JitHelp: CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER)
00007ffb`ba8d5314 48b8603fafbafb7f0000 mov rax,7FFBBAAF3F60h (gcstress)
00007ffb`ba8d531e 833800          cmp     dword ptr [rax],0 (gcstress)
00007ffb`ba8d5321 7405            je      00007ffb`bacb5d34 (gcstress)
00007ffb`ba8d5323 e8d8879a5e      call    CoreCLR!ProfToEEInterfaceImpl::GetClassIDInfo+0x53c (00007ffc`1965e50c) (gcstress) (JitHelp: CORINFO_HELP_DBG_IS_JUST_MY_CODE)
00007ffb`ba8d5328 90              nop (gcstress)

F:\git\runtime3\src\coreclr\tests\src\Interop\NativeCallable\NativeCallableTest.cs @ 160:
00007ffb`ba8d5329 8b4d10          mov     ecx,dword ptr [rbp+10h] (gcstress)
00007ffb`ba8d532c e857bafeff      call    00007ffb`baca1794 (gcstress) (Program.DoubleImpl(Int32), mdToken: 0000000006000003)
00007ffb`ba8d5331 8945f8          mov     dword ptr [rbp-8],eax (gcstress)
00007ffb`ba8d5334 8b4df8          mov     ecx,dword ptr [rbp-8] (gcstress)
00007ffb`ba8d5337 894dfc          mov     dword ptr [rbp-4],ecx (gcstress)
00007ffb`ba8d533a 90              nop (gcstress)
00007ffb`ba8d533b eb00            jmp     00007ffb`bacb5d49 (gcstress)

F:\git\runtime3\src\coreclr\tests\src\Interop\NativeCallable\NativeCallableTest.cs @ 161:
00007ffb`ba8d533d 8b4dfc          mov     ecx,dword ptr [rbp-4] (gcstress)
00007ffb`ba8d5340 894df4          mov     dword ptr [rbp-0Ch],ecx (gcstress)
00007ffb`ba8d5343 eb00            jmp     00007ffb`bacb5d51 (gcstress)
00007ffb`ba8d5345 488d4de0        lea     rcx,[rbp-20h] (gcstress)
00007ffb`ba8d5349 e862a89a5e      call    CoreCLR!ProfToEEInterfaceImpl::GetCodeInfo+0x1ec (00007ffc`196605bc) (gcstress) (JitHelp: CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT)
00007ffb`ba8d534e 8b45f4          mov     eax,dword ptr [rbp-0Ch] (gcstress)
00007ffb`ba8d5351 488d6500        lea     rsp,[rbp]
00007ffb`ba8d5355 5d              pop     rbp
00007ffb`ba8d5356 c3              ret

@janvorli That is issue #33612 and the fix is https://github.com/dotnet/runtime/pull/33615. I would merge in that change or comment out all other tests except for the exception ones.

@AaronRobinsonMSFT this is different. I have already applied your fix locally before. The disass of the managed method shows that it is not calling the JIT_ReversePInvokeEnter, so it has no place to create the native Thread object.

Let me try that locally. I don't recall observing any issue with that test.

I am not seeing that locally. Using COMPlus_jitdump=ManagedCallback_Prepared I get the following below. I am also able to step through the Enter/Exit and run COMPlus_GCStress=0xC and COMPlus_GCStress=0x3 without issue. Is there something I could be missing locally? I am using a Debug version of the runtime. Is it possible I need to try a Checked version?

------------ BB01 [???..???), preds={} succs={BB02}
N002 (  3,  3) [000010] ------------        t10 =    LCL_VAR_ADDR long   V03 tmp2          $101
                                                  /--*  t10    long
               [000019] ------------        t19 = *  PUTARG_REG long   REG rcx
                                                  /--*  t19    long   arg0 in rcx
N003 ( 17,  9) [000011] --C-G-------              *  CALL help void   HELPER.CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER $VN.Void

------------ BB02 [000..007), preds={BB01} succs={BB03}
N001 (  1,  1) [000000] ------------         t0 =    LCL_VAR   int    V00 arg0         u:1 (last use) $80
N002 (  1,  1) [000004] -c----------         t4 =    CNS_INT   int    1 $42
                                                  /--*  t0     int
                                                  +--*  t4     int
N003 (  3,  3) [000005] ------------         t5 = *  LSH       int    $140
                                                  /--*  t5     int
N005 (  3,  3) [000017] DA-----N----              *  STORE_LCL_VAR int    V02 tmp1         d:1

------------ BB03 [???..???) (return), preds={BB02} succs={}
N002 (  3,  3) [000013] ------------        t13 =    LCL_VAR_ADDR long   V03 tmp2          $103
                                                  /--*  t13    long
               [000020] ------------        t20 = *  PUTARG_REG long   REG rcx
                                                  /--*  t20    long   arg0 in rcx
N003 ( 17,  9) [000014] --C-G-------              *  CALL help void   HELPER.CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT $VN.Void
N001 (  1,  1) [000007] -------N----         t7 =    LCL_VAR   int    V02 tmp1         u:1 (last use) $140
                                                  /--*  t7     int
N002 (  2,  2) [000008] ------------              *  RETURN    int    $181

Okay. I see the issue now. I was only using a Release build of the test binary not a Debug version. I foolishly assumed the Release would uncover more issues than the Debug version.

Okay. So the issue here is it appears the GC stress something is inserted prior to the new reverse P/Invoke helper Enter/Exit. See the diasm below. I don't know enough about this to be able to make a fix. Any help would be appreciated.

*************** After end code gen, before unwindEmit()
G_M4921_IG01:        ; func=00, offs=000000H, size=001BH, bbWeight=1    PerfScore 5.08, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref, nogc, isz <-- Prolog IG

IN0015: 000000 push     rbp
IN0016: 000001 sub      rsp, 64
IN0017: 000005 lea      rbp, [rsp+40H]
IN0018: 00000A vxorps   xmm4, xmm4
IN0019: 00000E vmovdqa  xmmword ptr [rbp-20H], xmm4
IN001a: 000013 vmovdqa  xmmword ptr [rbp-10H], xmm4
IN001b: 000018 mov      dword ptr [V00 rbp+10H], ecx

G_M4921_IG02:        ; offs=00001BH, size=0018H, bbWeight=1    PerfScore 4.75, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref, isz

IN0001: 00001B lea      rcx, [V05 rbp-20H]
IN0002: 00001F call     CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER
IN0003: 000024 mov      rax, 0x7FFA10503F58
IN0004: 00002E cmp      dword ptr [rax], 0
IN0005: 000031 je       SHORT G_M4921_IG04

G_M4921_IG03:        ; offs=000033H, size=0005H, bbWeight=0.50 PerfScore 0.50, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref

IN0006: 000033 call     CORINFO_HELP_DBG_IS_JUST_MY_CODE

G_M4921_IG04:        ; offs=000038H, size=0015H, bbWeight=1    PerfScore 7.50, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref, isz

IN0007: 000038 nop
IN0008: 000039 mov      ecx, dword ptr [V00 rbp+10H]
IN0009: 00003C call     Program:DoubleImpl(int):int
IN000a: 000041 mov      dword ptr [V03 rbp-08H], eax
IN000b: 000044 mov      ecx, dword ptr [V03 rbp-08H]
IN000c: 000047 mov      dword ptr [V01 rbp-04H], ecx
IN000d: 00004A nop
IN000e: 00004B jmp      SHORT G_M4921_IG05

G_M4921_IG05:        ; offs=00004DH, size=0008H, bbWeight=1    PerfScore 4.00, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref, isz

IN000f: 00004D mov      ecx, dword ptr [V01 rbp-04H]
IN0010: 000050 mov      dword ptr [V04 rbp-0CH], ecx
IN0011: 000053 jmp      SHORT G_M4921_IG06

G_M4921_IG06:        ; offs=000055H, size=000CH, bbWeight=1    PerfScore 2.50, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref

IN0012: 000055 lea      rcx, [V05 rbp-20H]
IN0013: 000059 call     CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT
IN0014: 00005E mov      eax, dword ptr [V04 rbp-0CH]

G_M4921_IG07:        ; offs=000061H, size=0006H, bbWeight=1    PerfScore 2.00, epilog, nogc, extend

IN001c: 000061 lea      rsp, [rbp]
IN001d: 000065 pop      rbp
IN001e: 000066 ret


*************** Finishing PHASE Emit code

something is inserted prior to the new reverse P/Invoke helper

What is this "something"? I do not see it in the disassembly that you have shared.

The hlt instruction. That is what I am stepping through in Visual Studio. I didn't think the hlt would be emitted by the JIT, but am assuming it is a part of the GC Stress mechanism that triggers an exception. The failure point here is in ProcessCLRException() which fails to attempt a switch to COOP mode since the reverse PInvoke hasn't called the Enter yet and a thread doesn't yet exist.

My starting premise for all of this is the reverse PInvoke Enter would be the very first thing in the prolog. Perhaps this was a bad assumption.

00007FFA102C327E 00 00                add         byte ptr [rax],al  
00007FFA102C3280 55                   push        rbp  
00007FFA102C3281 48 83 EC 40          sub         rsp,40h  
00007FFA102C3285 48 8D 6C 24 40       lea         rbp,[rsp+40h]  
00007FFA102C328A C5 D8 57 E4          vxorps      xmm4,xmm4,xmm4  
00007FFA102C328E C5 F9 7F 65 E0       vmovdqa     xmmword ptr [rbp-20h],xmm4  
00007FFA102C3293 C5 F9 7F 65 F0       vmovdqa     xmmword ptr [rbp-10h],xmm4  
00007FFA102C3298 89 4D 10             mov         dword ptr [rbp+10h],ecx  
00007FFA102C329B F4                   hlt  
00007FFA102C329C 8D 4D E0             lea         ecx,[rbp-20h]  
00007FFA102C329F F4                   hlt  
00007FFA102C32A0 AC                   lods        byte ptr [rsi]

Boo. Yep. This is done by GCCoverageInfo::SprinkleBreakpoints().

Therefore the question here is should I update the GCCoverageInfo to know about this type of helper and move beyond it or ignore methods attributed with the NativeCallableAttribute. Other options?

The GC coverage can only instrument at places where real GC can take place. So it is rather a matter of generating correct GC info that should not make a native callable function interruptible before the JIT_ReversePInvokeEnter.

I believe that the same problem exists for the regular PInvoke. The instructions can be marked as fully interuptible, but still run in preemptive mode.

Can we just create the Thread when we are doing GC stress and hit the GC stress exception handler?

Ah, I haven't realized that the thread runs in a preemptive mode until it reaches the JIT helper. But it is weird that GC stress doesn't handle that already. And even stranger, how come Aaron's fix doesn't help, as the OnGcCoverageInterrupt with his fix is checking for NULL Thread and if it is the case, it should just silently remove the hlt and go without ever going into the ProcessCLRException. I'm stepping through the code to see if I can find a clue.

And even stranger, how come Aaron's fix doesn't help, as the OnGcCoverageInterrupt with his fix is checking for NULL Thread and if it is the case, it should just silently remove the hlt and go without ever going into the ProcessCLRException. I'm stepping through the code to see if I can find a clue.

@janvorli That is because this is the PrepareMethod() scenario where the function is JITed from a thread that is initialized and only called on a thread that is external.

@janvorli But you just pointed out to me how I think we can fix this.

@janvorli Nope. I misunderstood why this was happening. Looks like the COOP transition is happening before the call to IsGcMarker() which would handle the case I fixed.

    {
        GCX_COOP();
        // Update the current establisher frame
        if (dwExceptionFlags & EXCEPTION_UNWINDING)
        {
            ExceptionTracker *pCurrentTracker = pThread->GetExceptionState()->GetCurrentExceptionTracker();
            if (pCurrentTracker != NULL)
            {
                pCurrentTracker->SetCurrentEstablisherFrame(sf);
            }
        }

#ifdef _DEBUG
        Thread::ObjectRefFlush(pThread);
#endif // _DEBUG
    }


    //
    // begin Early Processing
    //
    {
#ifndef USE_REDIRECT_FOR_GCSTRESS
        if (IsGcMarker(pContextRecord, pExceptionRecord))
        {
            returnDisposition = ExceptionContinueExecution;
            goto lExit;
        }
#endif // !USE_REDIRECT_FOR_GCSTRESS

Can we just create the Thread when we are doing GC stress and hit the GC stress exception handler?

@jkotas Can you elaborate on this? @AndyAyersMS suggested I could update bool emitter::emitNoGChelper(CorInfoHelpFunc helpFunc) to have the Enter/Exit - the CORINFO_HELP_INIT_PINVOKE_FRAME is already present. Is that what you mean here?

It seems that the call to ProcessCLRException stems from something else than the GC coverage interrupt. I can see that the CLRVectoredExceptionHandlerShim correctly detects that the Thread is null and just removes the instrumentation and returns. And then a bit later, without any other CLRVectoredExceptionHandlerShim call, the ProcessCLRException is called and crash due to the Thread being NULL. There are hundreds of CLRVectoredExceptionHandlerShim calls to handle previous GC coverage interrupts before that and none of them results in a call to ProcessCLRException. So there is something happening that causes the call to occur (with error code 0xc0000096, which represents the coverage privileged instruction). I wonder if the CLRVectoredExceptionHandlerShim returns wrong return value or something like that. I keep looking...

Yep the call to CLRVectoredExceptionHandlerShim() is returning EXCEPTION_CONTINUE_SEARCH during that hlt for GC cover. What should it be returning?

I think I've found the culprit - testing now ...

Yes, I was right. The problem is that the fix @AaronRobinsonMSFT did in OnGcCoverageInterrupt in #33615 was insufficient. We also need to make sure that the CLRVectoredExceptionHandlerShim returns EXCEPTION_CONTINUE_EXECUTION when bIsGCMarker is true and pThread is NULL. We were currently returning EXCEPTION_CONTINUE_SEARCH, which resulted in the incorrect call to ProcessCLRException.

@janvorli I just tested that very scenario. My plan was to update if (pThread || fExceptionInEE) to if (pThread || fExceptionInEE || bIsGCMarker) in excep.cpp@7982?

I would put the following at line 7967. That is sufficient. I believe we don't need anything from the body of the if you've mentioned.

else if (bIsGCMarker)
{
    result = EXCEPTION_CONTINUE_EXECUTION;
}

I also have a fix for the other issue, I will create a PR soon.

I will fold the above into the previous PR so it is complete.

Was this page helpful?
0 / 5 - 0 ratings