Skip to content

[release/10.0] Fix NativeAOT GC hole issue#129711

Open
github-actions[bot] wants to merge 7 commits into
release/10.0from
backport/pr-129598-to-release/10.0
Open

[release/10.0] Fix NativeAOT GC hole issue#129711
github-actions[bot] wants to merge 7 commits into
release/10.0from
backport/pr-129598-to-release/10.0

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Backport of #129598 to release/10.0

/cc @janvorli

Customer Impact

  • Customer reported
  • Found internally

There is a GC hole in NativeAOT. As any other GC hole, it could lead to intermittent failures of applications due to unexpected NullReferenceException, AccessViolationException or just unexpected behavior. This GC hole occurs in some cases when GC scans stack with active exception handling when an exception thrown from a call chain of a funclet escapes the funclet and GC occurs when a finally handler of that secondary exception is being executed.

Regression

  • Yes
  • No

Introduced by #115284 in .NET 10.0

Testing

Libraries test that exposed the issue, directed regression test, CI coreclr and libraries tests.

Risk

Low. The change just ensures that a modified non-volatile register value is saved in the stack frame iterator of the pending exception handling, keeping that value up to date in case GC moves it.

janvorli and others added 7 commits June 22, 2026 19:17
There is a GC hole when:
* an exception is rethrown from a funclet
* the exception escapes that funclet
* a finally is executed for this secondary exception
* GC runs while the call chain of this finally is being executed
* A reference in non-volatile register is pushed in a prolog
  of one of the functions in the finally call chain
* the nonvolatile register holds a live reference up somewhere up
  in the call chain of the parent of the catch handler that catches
  the secondary exception
* the nonvolatile register is not pushed anywhere between the parent
  of the catch and the frame where the nonvolatile register holds
  a live GC reference

In this case, if GC relocates that reference, it is updated in the
stack frame of the finally call chain, but not in the location
referenced by the REGDISPLAY in the ExInfo of the secondary exception.
So when we resume after catch, the stale reference is placed in the
nonvolatile register and then it bubbles up the call chain until it
reaches the frame where the register is supposed to hold live GC
reference.

The fix is to save the nonvolatile registers after returning from a
finally funclet back to the location referenced by the REGDISPLAY passed
to the RhpCallFinallyFunclet.

Close #129010
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@janvorli janvorli requested a review from jkotas June 22, 2026 19:27
@janvorli janvorli self-assigned this Jun 22, 2026
@janvorli janvorli added this to the 10.0.x milestone Jun 22, 2026
@janvorli janvorli added area-NativeAOT-coreclr Servicing-consider Issue for next servicing release review labels Jun 22, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

@JulieLeeMSFT JulieLeeMSFT added Servicing-approved Approved for servicing release and removed Servicing-consider Issue for next servicing release review labels Jun 22, 2026

@JulieLeeMSFT JulieLeeMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Please get code review and check test failures when CI is done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-NativeAOT-coreclr Servicing-approved Approved for servicing release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants