This question is very similar to Using C++11 multithreading in shared library loaded by program without thread support
I have a shared library which uses OpenMP and a main program, which calls a function from that.
testlib.cpp
#include <memory>
void foo(std::shared_ptr<int> f)
{
#pragma omp parallel for
for (size_t g = 0; g < 100; g++) {
auto other = f;
}
}
tester.cpp
#include <memory>
void foo(std::shared_ptr<int> f);
int main() {
foo(std::make_shared<int>(4));
}
I compile and link with:
g++ -fPIC -g -shared -o libtestlibd.so testlib.cpp -openmp -pthread
g++ -g tester.cpp -o tester -Wl,-rpath,`pwd` libtestlibd.so
However when running this on a machine with a custom (automatically) build compiler, this crashes with "pure virtual method called", "SIGSEV" and similar which I traced to __gthread_active_p
returning false
even though it should not, after all the program is (transitively) linked to libpthread
With gdb I set breakpoints inside the __gthread_active_p
function with condition to trigger when the contained pointer is NULL or not, i.e. the function would return true or false.
I then compared the backtrace and the address of the variable:
- In both cases the call to
__gthread_active_p
originates fromfoo
, so from the shared library - The address of
__gthread_active_ptr
varies and is either set or not - However the situation where
__gthread_active_p
is, according to the addresses of the functions, when the shared_ptr destructor from the main program is called, i.e. I guess the dynamic linker found 2 definitions of it and chose to use the one from the main program
When doing the same on my Linux Mint 20 system the program works and debugging it shows that the destructor from the shared lib is used.
It also works, if I link the main program explicitly with -lpthread
, although I already link it with the shared lib, which links pthread.
The __gthread_active_p
function and the referenced variables are all static, i.e. local to the translation unit. Hence only my 2 cpp files matter.
So my questions are:
- Why is libpthread not loaded before the static variables of the main program are initialized?
- The function even contains a
static void *const
which to my understanding should only be initialized on the first call to the function. This doesn't seem to be true here, the debugger shows the first call from inside the shared lib, so after pthread is loaded. Why? - Is this a bug in libstdc++? This sounds like a massive footgun that you need to know, if any of your shared libs uses threading and if so link to pthread too.
- What could I check to find out why it happens in one environment but not the other, given the GCC and libstdc++ version are the same?