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).

Reply via email to