Skip to content

Commit ae6ad88

Browse files
authored
Fix wrong CONTEXT_UNWOUND_TO_CALL from special APC on ARM64 (#103731)
While testing an unrelated change, I've noticed that some coreclr tests were crashing on arm64 Windows with GCStress 3 intermittently. In all the cases, the special user mode APC callback was on the stack. It turned out that the context that the callback gets from the OS has the CONTEXT_UNWOUND_TO_CALL flag set, which is incorrect, as the context is the location of where the execution was interrupted is not unwound to call. That flag resulted in adjustment of the PC to the previous instruction. In the crashing cases, it adjusted it to a location of a "ret", so the unwinding just loaded PC from LR, which got an incorrect result. The effect of it was that in this case GC stack walk ended up prematurely, which resulted in GC holes. The fix is to clear the flag on the context we get from Windows.
1 parent 8382cf1 commit ae6ad88

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

src/coreclr/vm/threadsuspend.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5873,6 +5873,13 @@ void Thread::ApcActivationCallback(ULONG_PTR Parameter)
58735873
ActivationReason reason = (ActivationReason)pData->Parameter;
58745874
PCONTEXT pContext = pData->ContextRecord;
58755875

5876+
#if defined(TARGET_ARM64)
5877+
// Windows incorrectly set the CONTEXT_UNWOUND_TO_CALL in the flags of the context it passes to us.
5878+
// That results in incorrect compensation of PC at some places and sometimes incorrect unwinding
5879+
// and GC holes due to that.
5880+
pContext->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL;
5881+
#endif // TARGET_ARM64
5882+
58765883
if (!CheckActivationSafePoint(GetIP(pContext)))
58775884
{
58785885
return;

0 commit comments

Comments
 (0)