Skip to content

Publish GCHandle assignments with release semantics#130213

Merged
jkotas merged 1 commit into
dotnet:mainfrom
BradBarnich:gc-handle-release
Jul 5, 2026
Merged

Publish GCHandle assignments with release semantics#130213
jkotas merged 1 commit into
dotnet:mainfrom
BradBarnich:gc-handle-release

Conversation

@BradBarnich

Copy link
Copy Markdown
Contributor

Summary

Use release-store semantics when assigning GC handle slots in HndAssignHandle and HndAssignHandleGC.

On weakly ordered ARM64 systems, the previous plain store could publish an object reference through a GC handle before prior object initialization writes were visible to another thread observing that handle.
This can allow weak-reference readers to see partially initialized managed objects.

Details

GC handle assignment stores the raw object reference into the handle slot with a plain store:
https://github.com/dotnet/runtime/blob/main/src/coreclr/gc/handletable.inl#L47

  *(_UNCHECKED_OBJECTREF *)handle = value;

This changes that store to VolatileStore, making handle assignment a release publication point:

  VolatileStore((_UNCHECKED_OBJECTREF *)handle, value);

This matches the runtime's existing volatile publication pattern and ensures prior writes are visible before another thread can observe the object through the handle.

Discovered this via rare NullReferenceExceptions in Regex.Replace in an application when running on arm64 (10.0.9). The repro for that is https://gist.github.com/BradBarnich/4e6368d7e3ae5a32896852c146e0eb3f. It can take a lot of time to produce an error but was most reliable on graviton4. Never did produce on Mac.

This produced a dump file that showed the partial object (null ._rules) and focuses the analysis on the WeakReference

There is a shared WeakReference to RegexReplacement and the exception was thrown when it would sometimes observe a partially constructed RegexReplacement. The WeakReference.SetTarget is called after construction https://github.com/dotnet/runtime/blob/main/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexReplacement.cs#L107-L117

Internally WeakReference.SetTarget calls GCHandle.InternalSet https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs#L120

Validation

Validated with a focused WeakReference publication repro https://gist.github.com/BradBarnich/ccd7e3811cfbe4142ff7c85ec8305c76

Without the patch, the repro fails quickly on Mac and AWS arm64. Does not fail on x64.

When the patch, does not fail on Mac or AWS arm64

GC handles can be observed by other threads after assignment. On weakly ordered ARM64 systems, a plain store to the handle slot can publish the object reference before prior object initialization writes are visible to the observing thread.

Use VolatileStore when assigning handle slots in HndAssignHandle and HndAssignHandleGC so the handle publication is a release store. This matches the runtime's volatile publication pattern and prevents weak-reference readers from seeing partially initialized objects.
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Jul 5, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

@jkotas jkotas 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.

Good catch!

@jkotas jkotas merged commit 8f365c9 into dotnet:main Jul 5, 2026
116 of 121 checks passed
@jkotas

jkotas commented Jul 5, 2026

Copy link
Copy Markdown
Member

/backport to release/10.0

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 11.0-preview7 milestone Jul 6, 2026
JulieLeeMSFT pushed a commit that referenced this pull request Jul 6, 2026
…130224)

Backport of #130213 to release/10.0

/cc @jkotas @BradBarnich

## Customer Impact

- [x] Customer reported
- [ ] Found internally

Stress failure found on Arm64 caused by weak memory model 

## Regression

- [ ] Yes
- [x] No

## Testing

Customer validated the fix in the affected workload

## Risk

Low.

Co-authored-by: Brad Barnich <brad@careevolution.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-arm64 area-GC-coreclr community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants