https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118811

--- Comment #11 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Nicholas Williams from comment #0)
> Created attachment 60437 [details]
> Minimal reproduction application
> 
> I have discovered a SIGABRT (or, when ASAN is enabled, a heap-use-after-free
> report) in std::chrono::locate_zone() when it calls
> std::chrono::tzdb_list::begin() as a result of C++20 Chrono library use
> during application shutdown (exit handlers). I'm not able to attach our
> proprietary code, so I have attached a fully functional minimal replication
> application that successfully demonstrates the problem.

Doesn't your minimized program have a data race on the _running member?
_pInstance is also accessed without synchronization but is only accessed from
the main thread so that doesn't have a data race.

> From what I can tell reading through the ASAN report and the code in the
> chrono header, the problem appears to be related to the use of a chrono
> class's private static class data member that's a shared_ptr, without any
> checks about the validity of said shared_ptr. Since static class data
> members are destructed before static global variables,

Are they? Where is that specified?

> the shared_ptr in
> chrono gets destructed before our logging thread shared_ptr.

Like all objects with static storage duration, it gets destroyed in reverse
order of construction.

Because your logging thread shared_ptr is created early, before main, it is
constructed in an unspecified order compared to any other globals, including
the tzdb_list pointer. As Andrew said, there's a static initialization order
bug.

This should be fixable by using __attribute__((init_priority(x))) inside
libstdc++.

Reply via email to