Static initialization of boost shared objects question

Hello. Thanks for reading my question. I fell into a deadlock in static initialization of boost shared objects. The deadlock occurs in a reentrant call to a function which contains a definition of a static variable. Apparenlty gcc protects the initialization of such variables with a condition variable. Looking at the c++ code nothing at all make anybody suspect about reentrancy. My "interpretation of the fact" may be titled 'something in gcc, ld, ld.so, c++language made the call to be reentrant' - There is a function boost::system::generic_category() that has a static variable V - V type is boost::system::annonymous-namespace::generic_error_category - boost::system::annonymous-namespace::generic_error_category is subclass of boost::system::error_category. - boost::system::annonymous-namespace::generic_error_category has no declared/defined constructor as well as all its superclasses - The compilation process generate the constructor boost::system::error_category::error_category() as a weak symbol inside every shared object that uses it. - There is a static variable boost::system::posix_category in one of the shared objects that is initialized calling boost::system::generic_category(). - when the static initialization of a shared object boost::system::posix_category get initialized - which calls boost::system::generic_category() - Inside boost::system::generic_category() starts the initialization of V which calls boost::system::error_category::error_category() - It may happend that the runtime calls an instance of boost::system::error_category::error_category() that resides in a shared object that is still not loaded - So that .so get loaded and it is called its own static initialization - which can call boost::system::generic_category() - BOOM I would love if you can confirm of refute my humble "interpretation". Details follows ------------------- boost version: 1-52-0 Operating system: uname -a SunOS bcpp-solaris10 5.10 Generic_147441-25 i86pc i386 i86pc $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/export/home/local/gcc-4.6.2/libexec/gcc/i386-pc-solaris2.10/4.6.2/lto-wrapper Target: i386-pc-solaris2.10 Configured with: ../src/gcc-4.6.2/configure --prefix=/export/home/local/gcc-4.6.2 --with-gmp=/export/home/local/gcc-4.6.2/gmp-4.3.2 --with-mpfr=/export/home/local/gcc-4.6.2/mpfr-3.0.0 --with-mpc=/export/home/local/gcc-4.6.2/mpc-0.8.2 --with-libelf=/export/home/local/gcc-4.6.2/libelf-0.8.12 --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --enable-languages=c,c++ --with-as=/usr/local/bin/as --with-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-plugin --enable-multilib --enable-version-specific-runtime-libs --enable-bootstrap --enable-ssp --enable-libssp --with-included-gettext --enable-lto --host=i386-pc-solaris2.10 --build=i386-pc-solaris2.10 Thread model: posix gcc version 4.6.2 (GCC) Callstack backtrace (lines begining with = are my comments): = = deadlock here: the threads is waiting itself = #0 0xfd459019 in __lwp_park () from /lib/libc.so.1 #1 0xfd45365e in cond_sleep_queue () from /lib/libc.so.1 #2 0xfd453817 in cond_wait_queue () from /lib/libc.so.1 #3 0xfd453b94 in cond_wait_common () from /lib/libc.so.1 #4 0xfd453d02 in _cond_wait () from /lib/libc.so.1 #5 0xfd453d2d in cond_wait () from /lib/libc.so.1 #6 0xfd453d66 in pthread_cond_wait () from /lib/libc.so.1 #7 0xfd632898 in __gthread_cond_wait (g=0xfd822ea8) at ...build-gcc/out/i386-pc-solaris2.10/libstdc++-v3/include/i386-pc-solaris2.10/bits/gthr-default.h:846 #8 __gthread_cond_wait_recursive (g=0xfd822ea8) at ...work/build-gcc/out/i386-pc-solaris2.10/libstdc++-v3/include/i386-pc-solaris2.10/bits/gthr-default.h:860 #9 __gnu_cxx::__cond::wait_recursive (g=0xfd822ea8) at ...build-gcc/out/i386-pc-solaris2.10/libstdc++-v3/include/ext/concurrence.h:377 #10 __cxa_guard_acquire (g=0xfd822ea8) at .../src/gcc-4.6.2/libstdc++-v3/libsupc++/guard.cc:289 = = Reentrant call to boost::system::generic_category() = #11 0xfd812313 in boost::system::generic_category () at libs/system/src/error_code.cpp:425 #12 0xfe85cd38 in __static_initialization_and_destruction_0(__initialize_p=1, __priority=65535) at ./boost/system/error_code.hpp:214 #13 0xfe85d05f in _GLOBAL__sub_I_instantiate_re2c_lexer_str.cpp () at libs/wave/src/instantiate_re2c_lexer_str.cpp:56 = = static initization of boost.wave library = #14 0xfe8868fd in __do_global_ctors_aux () from ...boost/lib/libboost_wave-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0 #15 0xfe88692a in _init () from ...boost/lib/libboost_wave-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0 #16 0xfefce37e in call_init () from /usr/lib/ld.so.1 #17 0xfefce1cf in is_dep_init () from /usr/lib/ld.so.1 #18 0xfefdaa4b in elf_bndr () from /usr/lib/ld.so.1 #19 0xfefc2ab4 in elf_rtbndr () from /usr/lib/ld.so.1 #20 0xfee60688 in ?? () #21 0xfee0c8f6 in boost::exception_detail::get_static_exception_object<boost::exception_detail::bad_alloc_>() at ./boost/exception/detail/exception_ptr.hpp:119 #22 0xfee0c0d2 in __static_initialization_and_destruction_0(__initialize_p=1, __priority=65535) at ./boost/exception/detail/exception_ptr.hpp:138 #23 0xfee0c271 in _GLOBAL__sub_I_future.cpp () at libs/thread/src/future.cpp:60 = = static initization of boost.thread library = #24 0xfee0d98d in __do_global_ctors_aux () from ...boost/lib/libboost_thread-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0 #25 0xfee0d9ba in _init () from ...boost/lib/libboost_thread-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0 #26 0xfefce37e in call_init () from /usr/lib/ld.so.1 #27 0xfefce1cf in is_dep_init () from /usr/lib/ld.so.1 #28 0xfefdaa4b in elf_bndr () from /usr/lib/ld.so.1 #29 0xfefc2ab4 in elf_rtbndr () from /usr/lib/ld.so.1 #30 0xfdce0688 in ?? () = = First calll to boost::system::generic_category() = #31 0xfd81232a in boost::system::generic_category () at libs/system/src/error_code.cpp:425 #32 0xfd812386 in __static_initialization_and_destruction_0(__initialize_p=1, __priority=65535) at ./boost/system/error_code.hpp:214 #33 0xfd8123ed in _GLOBAL__sub_I_error_code.cpp () at libs/system/src/error_code.cpp:430 = = static initialization of boost.system = #34 0xfd8126ed in __do_global_ctors_aux () from ...boost/lib/libboost_system-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0 #35 0xfd81271a in _init () from ...boost/lib/libboost_system-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0 #36 0xfefce37e in call_init () from /usr/lib/ld.so.1 #37 0xfefcd7d5 in setup () from /usr/lib/ld.so.1 #38 0xfefdba3e in _setup () from /usr/lib/ld.so.1 #39 0xfefc299c in _rt_boot () from /usr/lib/ld.so.1 #40 0x08047540 in ?? () #41 0x08047670 in ?? () More thanks for reading all.

On Fri, Jan 25, 2013 at 2:19 PM, Juan Carlos Franzoy <jfranzoy@gmail.com> wrote:
Hello. Thanks for reading my question.
Posts stand a better chance of being read by the right person if they include the library name in square brackets at the beginning of the subject line. For example, "[regex]" or "[filesystem]". The subject line should not begin with "[boost]" as that is added automatically. See http://www.boost.org/community/policy.html#subject-line
I fell into a deadlock in static initialization of boost shared objects.
The deadlock occurs in a reentrant call to a function which contains a definition of a static variable. Apparenlty gcc protects the initialization of such variables with a condition variable.
Looking at the c++ code nothing at all make anybody suspect about reentrancy.
My "interpretation of the fact" may be titled 'something in gcc, ld, ld.so, c++language made the call to be reentrant'
Are you saying that a data race occurs during static initialization, and that causes a deadlock? Does this always occur with programs that use Boost System, or only when combined with Wave? Have you tried to construct a simple test program that illustrates the problem? --Beman

Posts stand a better chance of being read by the right person if they include the library name in square brackets at the beginning of the subject line. For example, "[regex]" or "[filesystem]". The subject
I agree, thanks. But in this specific case I do not know if it is specific to a library. I thought it could be off-topic, that it could be a compiler or linker issue. Then, as I was unsure, I decided to post it anyway. I found the "presumed problem" because of an error: I was linking to ALL boost libraries. When I corrected to link only with Boost.System and Boost.Filesystem and the problem didn't happen.
Are you saying that a data race occurs during static initialization, and that causes a deadlock?
I do not see a data race at all in c++ code. My "thesis" is that gcc/ld/ld.so may introduce reentrancy in any function called at static initialization time if this function refer to a symbol defined in another shared library. This occurs because the load of other shared library starts the static initialization of that shared library. If you add the fact that inline functions or compiler generated members are instantiated as weak symbols in all shared libraries that uses them, you end up with a lot of candidates of unintentional calls from one shared library to another. Please refer to the original post. This would disable calling inline function of compiler generated members from non-reentrant functions called at static initialization. Note: I want to know if this reasoning is correct.
Does this always occur with programs that use Boost System, or only when combined with Wave?
Only linking to a lot of the libraries.
Have you tried to construct a simple test program that illustrates the problem?
Yes I did, but I did not succed.

Has anyone looked into this issue, I am also experiencing the deadlock issue described above when using the boost libraries build in debug mode (GCC 1.48.0, 64bit) -- View this message in context: http://boost.2283326.n4.nabble.com/Static-initialization-of-boost-shared-obj... Sent from the Boost - Dev mailing list archive at Nabble.com.

2013/6/30 Chris Stylianou <chris5287@gmail.com>:
Has anyone looked into this issue, I am also experiencing the deadlock issue described above when using the boost libraries build in debug mode (GCC 1.48.0, 64bit)
As a workaround you could use LD_PRELOAD to force shared object order. In my case LD_PRELOAD=/.../boost_system... worked.
participants (3)
-
Beman Dawes
-
Chris Stylianou
-
Juan Carlos Franzoy