Skip to content

[release/10.0] Fix missing release semantics in VolatilePtr#124070

Open
hoyosjs wants to merge 1 commit intodotnet:release/10.0from
hoyosjs:juhoyosa/test-volatile-fix
Open

[release/10.0] Fix missing release semantics in VolatilePtr#124070
hoyosjs wants to merge 1 commit intodotnet:release/10.0from
hoyosjs:juhoyosa/test-volatile-fix

Conversation

@hoyosjs
Copy link
Member

@hoyosjs hoyosjs commented Feb 6, 2026

Related issue: #124071
Main PR: #124096

Risk: Low, purely adds a barrier which is the intended semantics of the class.

Impact: Detected as a non-deterministic lock free race that resulted in crashes in the Roslyn language server for internal customers. Mostly happens with really complex solutions that have a lot of threads accessing GC Statics.

VolatilePtr inherits from Volatile<P>, which defines operator= to call VolatileStore() with platform scpecific release semantics. However, VolatilePtr did not declare its own operator=, so the compiler-generated copy/move assignment operator hid the base class operator= and performed plain stores instead, bypassing memory barriers entirely.

Fix by adding a using declaration to bring Volatile<P>::operator= into scope, and an explicit copy assignment operator (which the using declaration cannot suppress the compiler from generating).

VolatilePtr inherits from Volatile<P>, which defines operator=(P val)
to call VolatileStore() with release semantics (stlr on ARM64). However,
VolatilePtr did not declare its own operator=, so the compiler-generated
copy/move assignment operator hid the base class operator= and performed
plain stores (str) instead, bypassing the memory barrier entirely.

This affected all VolatilePtr assignments including DeadlockAwareLock's
m_pHoldingThread and Thread's m_pBlockingLock fields, which were being
written without release semantics despite being read with acquire
semantics (ldapr) on the other side.

Fix by adding a using declaration to bring Volatile<P>::operator= into
scope, and an explicit copy assignment operator (which the using
declaration cannot suppress the compiler from generating).
Copilot AI review requested due to automatic review settings February 6, 2026 05:14
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Feb 6, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a critical memory barrier bug in the VolatilePtr template class. The class inherits from Volatile<P> which provides an operator= that uses release semantics (via VolatileStore). However, the compiler-generated copy/move assignment operators were hiding the base class operator, resulting in plain stores without memory barriers. This affected thread synchronization primitives like DeadlockAwareLock::m_pHoldingThread and Thread::m_pBlockingLock, where writes lacked release semantics despite corresponding reads using acquire semantics.

Changes:

  • Added using Volatile<P>::operator=; declaration to bring the base class assignment operator into scope
  • Added explicit copy assignment operator operator=(const VolatilePtr<T,P>&) to handle copy assignment with proper memory barriers
  • Applied the fix consistently to both src/coreclr/inc/volatile.h and src/coreclr/gc/env/volatile.h

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/coreclr/inc/volatile.h Fixes VolatilePtr to preserve release semantics by adding using declaration and explicit copy assignment operator
src/coreclr/gc/env/volatile.h Same fix as above for the GC subsystem's copy of the volatile.h header

@hoyosjs
Copy link
Member Author

hoyosjs commented Feb 6, 2026

/backport to main

@github-actions
Copy link
Contributor

github-actions bot commented Feb 6, 2026

Started backporting to main (link to workflow run)

@hoyosjs hoyosjs marked this pull request as ready for review February 6, 2026 18:11
@hoyosjs
Copy link
Member Author

hoyosjs commented Feb 7, 2026

/backport to release/9.0

@github-actions
Copy link
Contributor

github-actions bot commented Feb 7, 2026

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

@hoyosjs
Copy link
Member Author

hoyosjs commented Feb 7, 2026

/backport to release/8.0

@github-actions
Copy link
Contributor

github-actions bot commented Feb 7, 2026

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

@hoyosjs
Copy link
Member Author

hoyosjs commented Feb 7, 2026

/backport to release/8.0-staging

@hoyosjs
Copy link
Member Author

hoyosjs commented Feb 7, 2026

/backport to release/9.0-staging

@github-actions
Copy link
Contributor

github-actions bot commented Feb 7, 2026

Started backporting to release/8.0-staging (link to workflow run)

@github-actions
Copy link
Contributor

github-actions bot commented Feb 7, 2026

Started backporting to release/9.0-staging (link to workflow run)

@hoyosjs hoyosjs changed the title Fix missing release semantics in VolatilePtr [release/10.0] Fix missing release semantics in VolatilePtr Feb 7, 2026
@hoyosjs hoyosjs enabled auto-merge (squash) February 7, 2026 01:30
@AaronRobinsonMSFT AaronRobinsonMSFT added this to the 10.0.x milestone Feb 7, 2026
@AaronRobinsonMSFT AaronRobinsonMSFT added Servicing-consider Issue for next servicing release review and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Feb 7, 2026
@dotnet-policy-service
Copy link
Contributor

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

@AaronRobinsonMSFT
Copy link
Member

AaronRobinsonMSFT commented Feb 7, 2026

I have some concerns about this area. Not necessarily in these targeted changes but in the design itself. There is a lot of confusion in this implementation with respect to correct C++ design patterns and the issue being addressed here is simply one in a series of bad assumptions with respect to C++.

I'm not convinced the solution here is even appropriate/sufficient at present. What is our servicing timeline here?

@AaronRobinsonMSFT
Copy link
Member

I have some concerns about this area. Not necessarily in these targeted changes but in the design itself. There is a lot of confusion in this implementation with respect to correct C++ design patterns and the issue being addressed here is simply one in a series of bad assumptions with respect to C++.

I'm not convinced the solution here is even appropriate/sufficient at present. What is our servicing timeline here?

Okay, I see there is additional work being referenced in #124096 (comment).

so the compiler-generated copy/move assignment operator hid the base class

The above statement is my primary concern. I'd like to understand how this has been tested and validated with respect to use. I only note a copy assignment being exposed here, which when declared should disable auto generation of move assignment, MSVC has historical had slightly different rules here. I'd like to ensure we have audited all use sites and verified what MSVC is doing and what clang/gcc is doing. As I said, this narrow fix does seem appropriate at first glance but understanding the scope of the problem is needed in my opinion.

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

Labels

area-VM-coreclr Servicing-consider Issue for next servicing release review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants