https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111676
Bug ID: 111676 Summary: Race condition in std::ios::Init Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- #include <ios> #include <thread> void f() { std::ios::Init i; } int main() { std::thread t1(f); std::thread t2(f); t1.join(); t2.join(); } A possible execution for this program is: t1 runs the Init constructor which increments Init::_S_refcount to 1 and performs the one-time initialization of the global streams. t2 runs the Init constructor and increments the refcount to 2. t2 runs the ~Init destructor, which decrements the refcount to 1 and so flushes the global streams (while still under construction). t1 finishes constructing the global streams, and increments _S_refcount to 2. t1 runs the ~Init destructor, which decrements the refcount to 1 and so flushes the global streams again. Flushing twice isn't a problem, but t2 should block until t1 finishes constructing them, so that it doesn't flush objects that haven't finished initialization yet. We could just use a local static so that the __cxa_guard routines are used to make the second thread block until the initialization is complete.