Skip to content

Commit

Permalink
Fix wrong CONTEXT_UNWOUND_TO_CALL from special APC on ARM64 (#103731)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
janvorli committed Jun 20, 2024
1 parent 8382cf1 commit ae6ad88
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/coreclr/vm/threadsuspend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5873,6 +5873,13 @@ void Thread::ApcActivationCallback(ULONG_PTR Parameter)
ActivationReason reason = (ActivationReason)pData->Parameter;
PCONTEXT pContext = pData->ContextRecord;

#if defined(TARGET_ARM64)
// Windows incorrectly set the CONTEXT_UNWOUND_TO_CALL in the flags of the context it passes to us.
// That results in incorrect compensation of PC at some places and sometimes incorrect unwinding
// and GC holes due to that.
pContext->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL;
#endif // TARGET_ARM64

if (!CheckActivationSafePoint(GetIP(pContext)))
{
return;
Expand Down

0 comments on commit ae6ad88

Please sign in to comment.