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

            Bug ID: 97211
           Summary: __cxa_guard_acquire fails to detect recursive init in
                    multithreaded code
           Product: gcc
           Version: 11.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: ---

In a single-threaded program this detects recursive init:

#include <stddef.h>

int a() {
        static int xx = a();
        return 1;
}
extern "C" void* b(void*)
{
        a();
        return NULL;
}

int main() {
        b(NULL);
}

terminate called after throwing an instance of
'__gnu_cxx::recursive_init_error'
  what():  std::exception
Aborted (core dumped)


When we know there are no threads in the program we can assume that attempting
to acquire the guard variable when it's already in progress means recursive
init. Because no other thread exists, so it must have been the current thread
that started it, and we've re-entered the initialization.

But if there are multiple threads we just go to sleep waiting forever for
initialization to finish:

#include <pthread.h>
int a() {
        static int xx = a();
        return 1;
}
extern "C" void* b(void*)
{
        a();
        return NULL;
}

int main() {
        pthread_t thrd;
        pthread_create(&thrd, NULL, b, NULL);
        pthread_join(thrd, NULL);
}

Clang makes this work by storing the result of SYS_gettid in the last four
bytes of the guard variable, so it can detect when the same thread re-enters
the guard.

Reply via email to