Uh oh!
There was an error while loading. Please reload this page.
Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #127638
Conversation
…ort() with COMPlusCheckForAbort() in RestoreContextSimulated Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/8fa490ef-11e1-443a-bf1d-8d2d2dc09add Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
!m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Tagging subscribers to this area: @agocke |
Uh oh!
There was an error while loading. Please reload this page.
…rectedHandledJITCase Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/c055bf10-808a-4e92-9cee-1841d7cfd155 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a win-x86-specific debug assert (!m_RedirectContextInUse) by removing a re-entrancy window where RestoreContextSimulated could call HandleThreadAbort() while the redirect context was still marked “in use”. The change aligns the x86 SEH-based restore path with the existing shared abort-check flow used by the RtlRestoreContext path.
Changes:
- Remove the
HandleThreadAbort()call fromRestoreContextSimulatedso it performs only the SEH-based context restore mechanics. - Move the x86 “no
RtlRestoreContext” call toRestoreContextSimulatedto after the sharedCopyOSContext+COMPlusCheckForAbort()logic inRedirectedHandledJITCase.
Uh oh!
There was an error while loading. Please reload this page.
daigs
commented
May 21, 2026
VSadov
commented
Jul 20, 2026
/backport to release/10.0 |
Started backporting to |
@VSadov backporting to git am output$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchCreating an empty commit: Initial planApplying: Fix !m_RedirectContextInUse assert on win-x86: replace HandleThreadAbort() with COMPlusCheckForAbort() in RestoreContextSimulatedApplying: Refactor: move RestoreContextSimulated call after abort check in RedirectedHandledJITCaseerror: sha1 information is lacking or useless (src/coreclr/vm/threadsuspend.cpp).error: could not build fake ancestorhint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0003 Refactor: move RestoreContextSimulated call after abort check in RedirectedHandledJITCaseError: The process '/usr/bin/git' failed with exit code 128 |

main PR
Description
On x86 Windows without
RtlRestoreContext,RestoreContextSimulatedcalledHandleThreadAbort()whilem_RedirectContextInUsewas stilltrue.HandleThreadAbort()constructs aThreadAbortExceptionby running managed code (resource string loading, etc.), during which a concurrent GC redirect firesMarkRedirectContextInUse()→ assert!m_RedirectContextInUse.Fix: Move the
RestoreContextSimulatedcall inRedirectedHandledJITCaseto after the existingCOMPlusCheckForAbort()block, so both the x86 SEH path and theRtlRestoreContextpath share a single abort-check code path:CopyOSContext+COMPlusCheckForAbort()(bothNOTHROW/GC_NOTRIGGER— no managed code) run unconditionally for all platformspCtxIP is redirected toThrowControlForThreadand the resume PC is stored inm_OSContextRtlRestoreContext,RestoreContextSimulatedis then called (using the already-computed abort redirect); theEXCEPTION_HIJACKpath in its exception filter pops theRedirectedThreadFrameand callsUnmarkRedirectContextInUsebefore resumingRestoreContextSimulateditself is kept minimal — it contains only the SEH-based context-restore machinery with no abort logic. No code is duplicated between the two paths.The abort exception is now raised only after the redirect context is fully released, eliminating the re-entrancy window.
Customer Impact
Checked (debug) builds of .NET on Windows x86 crash with
STATUS_FAIL_FAST_EXCEPTIONwhenControlledExecution.Run(or any code path that triggers a thread abort) races with a GC redirect on the same thread. Release builds are not protected by the assert but the re-entrant redirect corrupts the saved context.Regression
Not a regression introduced in the most recent release; latent race in the x86-only
RestoreContextSimulatedpath.Testing
Built
clr.runtime(checked) with 0 errors/0 warnings. The affected code path is x86 Windows–specific (#ifdef TARGET_X86/#ifndef TARGET_UNIX) and not exercisable in a Linux x64 CI environment; the fix aligns the x86 SEH path with the existing non-x86 abort-redirect pattern that is already proven correct on all other platforms.Risk
Low. The change moves the
RestoreContextSimulatedcall to after the sharedCOMPlusCheckForAbortblock inRedirectedHandledJITCase, eliminating code duplication while preserving identical runtime behaviour. No new mechanism is introduced.Package authoring no longer needed in .NET 9
IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.