https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99341
Bug ID: 99341
Summary: [11 Regression] new std::call_once is not backwards
compatible
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Keywords: ABI
Severity: blocker
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: redi at gcc dot gnu.org
Target Milestone: ---
Target: *-*-*linux*
Creating a new bug for bug 66146 comment 41 increased visibility, and to deal
with it separately from the exception-handling bug that is the topic of bug
66146.
Quoting from there:
The new std::call_once using a futex is not backwards compatible, so I think it
needs to be reverted, or hidden behind an ABI-breaking flag.
The new std::once_flag::_M_activate() function sets _M_once=1 when an
initialization is in progress.
With glibc, if a call to the new std::call_once happens before a call to the
old version of std::call_once, then glibc's pthread_once will find no fork
generation value in _M_once and so will think it should run the init_function
itself. Both threads will run their init_function, instead of the second one
waiting for the first to finish.
With musl, if a call to the old std::call_once happens before a call to the new
std::call_once, then the second thread won't set _M_once=3 and so musl's
pthread_once won't wake the second thread when the first finishes. The second
thread will sleep forever (or until a spurious wake from the futex wait).