I'm trying to debug a C++ program compiled with GCC that freezes at startup. GCC mutex protects function's static local variables, and it appears that waiting to acquire such a lock is why it freezes. How this happens is rather confusing. First module A's static initialization occurs (there are __static_init functions GCC invokes that are visible in the backtrace), which calls a function Foo(), that has a static local variable. The static local variable is an object who's constructor calls through several layers of functions, then suddenly the backtrace has a few ??'s, and then it's is in the static initialization of a second module B (the __static functions occur all over again), which then calls Foo(), but since Foo() never returned the first time the mutex on the local static variable is still set, and it locks.
How can one static init trigger another? My first theory was shared libraries -- that module A would be calling some function in module B that would cause module B to load, thus triggering B's static init, but that doesn't appear to be the case. Module A doesn't use module B at all. So I have a second (and horrifying) guess. Say that:
Module A uses some templated function or a function in a templated class, e.g.
foo<int>::bar()
Module B also uses
foo<int>::bar()
Module A doesn't depend on module B at all
At link time, the linker has two instances of
foo<int>::bar()
, but this is OK because template functions are marked as weak symbols...At runtime, module A calls
foo<int>::bar
, and the static init of module B is triggered, even though module B doesn't depend on module A! Why? Because the linker decided to go with module B's instance of foo::bar instead of module A's instance at link time.
Is this particular scenario valid? Or should one module's static init never trigger static init in another module?
Clarification: GCC creates the mutexes automatically to guard any function static variable. I'm not doing anything with mutexes myself. It's GCC's way of making function static variables thread safe.
Update: I know that static initialization is not defined between translation units and that I shouldn't depend on an order. But I'm curious if this is normal behavior as a clue towards debugging the problem. Is it normal for a compiler to generate code that does this or is it potentially indicative of a bug in GCC?