https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91737
Bug ID: 91737 Summary: On Alpine Linux (libmusl) a statically linked C++ program which throws the first exception in two threads at the same time can busy spin on shutdown after main(). Product: gcc Version: 8.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libgcc Assignee: unassigned at gcc dot gnu.org Reporter: max at arangodb dot com Target Milestone: --- Created attachment 46870 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46870&action=edit Program exposing the problem when compiled under Alpine Linux and linked statically. My statically linked program runs a busy loop after main() has terminated, provided that the very first exception that is thrown in the run is thrown in two threads at the very same time. The attached program shows the problem. This only happens on Linux, and only if one does not use glibc as C-library, and only if the executable is statically linked and does not explicitly use the `pthread_cancel` function. I tested with g++ 8.3.0, but I think the problem is present in other versions as well. Here is what is happening: In the file `libgcc/unwind-dw2-fde.c` in the function `_Unwind_Find_FDE` there is a mutex which is only acquired if the underlying program is detected to be "multi-threaded". This test for multi-threadedness is done differently on various platforms (see file `libgcc/gthr-posix.h` lines 156 to 306). On Linux without glibc and if it is not the Android bionic C library, a weak reference to the symbol `pthread_cancel` is used. If the underlying program does not explicitly use `pthread_cancel` (and few C++ programs will, because cancelling threads is not in the C++ standard), and the linking is done statically, the program will link `libpthread` but not have a symbol `pthread_cancel`. In this case the mutex is not used at all. If now the first exception in the program happens in two exceptions concurrently, the function `_Unwind_Find_FDE` will move an object from the static list `unseen_objects` to the static list `seen_objects` and a data race occurs. Sometimes, the same object is moved twice from one list to the other. This leads to the fact that the `seen_objects` list ends in an object which points to itself (with the `next` pointer). In this case, on shutdown, well after main() and all static destructors, the function `__deregister_frame_info_bases` will busy loop running around the circular data structure `seen_objects`. I think this is overoptimized and the multi-threadedness detection does not work for many statically linked programs when libmusl is used as underlying C-library.