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
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.
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!
Fixed upstream now.
The final patch was more complicated than discussed: https://gcc.gnu.org/r16-6658-g5f02ba92580040
That's nice! It also makes the logic easier to follow