Bug 2427898

Summary: std::atomic asserting in wait()
Product: [Fedora] Fedora Reporter: alan
Component: gccAssignee: Jonathan Wakely <jwakely>
Status: NEW --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: rawhideCC: dmalcolm, fweimer, jakub, jlaw, josmyers, jwakely, mcermak, mpolacek, msebor, ngompa13, nickc, nixuser, sipoyare
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description alan 2026-01-08 11:55:11 UTC
Description of problem:

../../../../../libstdc++-v3/src/c++20/atomic.cc:323: bool std::__detail::__wait_args::_M_setup_proxy_wait(const void*): Assertion '_M_obj == addr' failed.

Version-Release number of selected component (if applicable):

GCC 16

How reproducible:


Steps to Reproduce:
1.

#include <atomic>
#include <thread>

int main() {
   std::atomic<bool> raised{false};

   std::jthread t{[&]{ raised.store(true); raised.notify_all(); }};

   raised.wait(false);
}

2.

g++ -g main.cpp &&  ./a.out

3.

Actual results:

../../../../../libstdc++-v3/src/c++20/atomic.cc:323: bool std::__detail::__wait_args::_M_setup_proxy_wait(const void*): Assertion '_M_obj == addr' failed.
Aborted                    (core dumped) ./a.out

Expected results:

Success

Comment 1 Jonathan Wakely 2026-01-08 13:33:45 UTC
The assertion fails if we loop in atomic<T>::wait where a proxy wait is used for T (i.e. it's not futex-sized). After the first iteration we've decided to do a proxy wait and updated _M_obj to point to the futex in the proxy state, and so _M_obj no longer matches the address of the atomic<T>.

Instead of:

   if (!use_proxy_wait(*this, addr)) // We can wait on this address directly.
    {
      // Ensure the caller set _M_obj correctly, as that's what we'll wait on:
      __glibcxx_assert(_M_obj == addr);
      return false;
    }

it should be:

   if (_M_obj == addr && !use_proxy_wait(*this, addr))
     return false; // We can wait on this address directly.

Comment 2 Jonathan Wakely 2026-01-08 15:42:11 UTC
Actually it would be better if the header code didn't call into the library again. It should only need to setup the proxy wait once, because if a proxy wait is needed once, it's needed every time!

Comment 3 Jonathan Wakely 2026-01-09 22:07:20 UTC
Fixed upstream now.

Comment 4 Jonathan Wakely 2026-01-12 11:42:19 UTC
The final patch was more complicated than discussed:
https://gcc.gnu.org/r16-6658-g5f02ba92580040

Comment 5 alan 2026-01-13 14:18:42 UTC
That's nice! It also makes the logic easier to follow