c++ static initialization question
Juan Carlos Franzoy
jfranzoy@gmail.com
Sat Jan 19 18:36:00 GMT 2013
Thanks for reading my question.
I'm experiencing a dealock in the initialization of a static variable
X defined inside a function Y called in the program static
initialization.
The problem, as far as I suppose ("as far as I know" would be an
exaggeration), is that gcc protects the the expression that
initializes X
from it beeing initialized concurrently by another thread and Y get
called reentrantly.
The question to answer would be, why is Y called reentrantly?
I think this problem relates to an old one I had in march 2010:
http://gcc.gnu.org/ml/gcc-help/2010-03/msg00090.html. In that problem
the deadlock was in my code and I could fix it.
The 'real' problem I had to resolve arises using boost. In this case Y
is boost::system::generic_category and X is a variable of type
generic_error_category.
I could reproduce the problem (well I suppose) although somewhat
artificially using three small shared libraries and a lot of confused
code.
Details
---------
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)
Details of the real problem using boost
----------------------------------------------------
Callstack backtrace (lines begining with = are my comments):
=
= deadlock 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
/export/home/bcpp/mlevalle/work/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
/export/home/bcpp/mlevalle/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
/export/home/bcpp/mlevalle/work/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
=
= This seems to be a reentrant call to
boost::system::generic_category(), although there is no reentrancy in
the c++ code.
= This function boost::system::generic_category() has an static
variable inside whose constructor is empty (including all base class
contructors)
=
= My humble interpretation is that gcc generates the empty constructor
as a weak symbol in various of the boost libraries shared object, then
at runtime
= or link time one is chosen. That causes that error_code.cpp in
boost_system.so triggers the load and static initialization of other
boost shared
= objects that ends up calling reentrantly the same function.
=
#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
#14 0xfe8868fd in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/nuevorep/BCPP/Modulos/legacy/boost/lib/libboost_wave-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0
#15 0xfe88692a in _init () from
/export/home/bcpp/jfranzoy/nuevorep/BCPP/Modulos/legacy/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
#24 0xfee0d98d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/nuevorep/BCPP/Modulos/legacy/boost/lib/libboost_thread-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0
#25 0xfee0d9ba in _init () from
/export/home/bcpp/jfranzoy/nuevorep/BCPP/Modulos/legacy/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 ?? ()
=
= This function boost::system::generic_category() has an static
variable inside whose constructor is empty (including all base class
contructors)
=
#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
#34 0xfd8126ed in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/nuevorep/BCPP/Modulos/legacy/boost/lib/libboost_system-gcc46-mt-d-32-SOLARIS-X86-1_52.so.1.52.0
#35 0xfd81271a in _init () from
/export/home/bcpp/jfranzoy/nuevorep/BCPP/Modulos/legacy/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 ?? ()
Details of the artificial problem as I could reproduce
--------------------------------------------------------------------
The files:
*** a.hpp ***
#ifndef AAA_HPP_INCLUDED
#define AAA_HPP_INCLUDED
#include <string>
class AAA {
std::string aaa_;
public:
explicit AAA(int i);
int get() const;
};
class DDD {
int i_;
public:
DDD();
int get() const;
};
extern DDD ddd;
#endif /* AAA_HPP_INCLUDED */
*** end of a.hpp ***
*** a.cpp ***
#include <cerrno>
#include <iostream>
#include "a.hpp"
#include "b.hpp"
AAA::AAA(int i ) : aaa_( "PEPE" ) {
std::cerr << "AAA::AAA(" << i << ")='" << this << "'" << std::endl;
}
int AAA::get() const {
std::cerr << "AAA::get()='" << this << "'" << std::endl;
return 10;
}
DDD::DDD() {
std::cerr << "DDD::DDD()='" << this << "' bbb1(10)=" << bbb1(10)
<< std::endl;
i_ = errno;
}
int DDD::get() const {
return i_;
}
DDD ddd;
*** end of a.cpp ***
*** b.hpp ***
#ifndef BBB_HPP_INCLUDED
#define BBB_HPP_INCLUDED
int bbb1(int i);
#endif /* BBB_HPP_INCLUDED */
*** end of b.hpp ***
*** b.cpp ***
#include <iostream>
#include "a.hpp"
int bbb1(int i) {
std::cerr << "bbb1(" << i << ")" << std::endl;
static AAA a( i );
return a.get();
}
*** end of b.cpp ***
*** c.hpp ***
#ifndef CCC_HPP_INCLUDED
#define CCC_HPP_INCLUDED
int ccc1();
#endif /* CCC_HPP_INCLUDED */
*** end of c.hpp ***
*** c.cpp ***
#include <iostream>
#include "b.hpp"
#include "c.hpp"
class CCC {
public:
CCC() {
std::cerr << "CCC::CCC()='" << this << "' bbb1(10)=" <<
bbb1(10) << std::endl;
}
};
CCC ccc;
*** end of c.cpp ***
*** d.cpp ***
#include <iostream>
#include "a.hpp"
#include "b.hpp"
int main() {
return ddd.get();
}
*** end of d.cpp ***
The command to compile them:
g++ -std=c++0x --shared -fPIC -O0 -oa.so -g a.cpp
g++ -std=c++0x --shared -fPIC -O0 -ob.so -g b.cpp
g++ -std=c++0x --shared -fPIC -O0 -oc.so -g c.cpp
g++ -std=c++0x -fPIC -O0 -od c.so a.so b.so d.cpp
The debugging session (comments start with =):
solaris10:~/jfranzoy/tmp> /export/home/local/gdb-7.1/bin/gdb d
GNU gdb (GDB) 7.1
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-pc-solaris2.10".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /export/home/bcpp/jfranzoy/tmp/d...(no debugging
symbols found)...done.
=
=
= I put breakpoints in every user defined function of function member
= and in all __static_initialization_and_destruction_0. In every breakpoint
= the call stack backtrace and the disassembly of the function is printed
=
(gdb) b a.cpp:__static_initialization_and_destruction_0
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n])
Breakpoint 1 (a.cpp:__static_initialization_and_destruction_0)
pending.
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b b.cpp:__static_initialization_and_destruction_0
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n])
Breakpoint 2 (b.cpp:__static_initialization_and_destruction_0) pending.
(gdb) commands
Type commands for when breakpoint 2 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b c.cpp:__static_initialization_and_destruction_0
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n])
Breakpoint 3 (c.cpp:__static_initialization_and_destruction_0) pending.
(gdb) commands
Type commands for when breakpoint 3 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b d.cpp:__static_initialization_and_destruction_0
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n])
Breakpoint 4 (d.cpp:__static_initialization_and_destruction_0)
pending.
(gdb) s
The program is not being run.
(gdb) silent
Undefined command: "silent". Try "help".
(gdb) bt
No stack.
(gdb) disassemble
No frame selected.
(gdb) cont
The program is not being run.
(gdb) end
This command cannot be used at the top level.
(gdb)
This command cannot be used at the top level.
(gdb) b AAA::AAA
y
comCan't find member of namespace, class, struct, or union named "AAA::AAA"
Hint: try 'AAA::AAA<TAB> or 'AAA::AAA<ESC-?>
(Note leading single quote.)
Make breakpoint pending on future shared library load? (y or [n])
Please answer y or [n].
Make breakpoint pending on future shared library load? (y or [n]) mands
Please answer y or [n].
Make breakpoint pending on future shared library load? (y or [n]) silent
bt
disassemble
cont
end
b AAA::get
y
comPlease answer y or [n].
Make breakpoint pending on future shared library load? (y or [n])
Please answer y or [n].
Make breakpoint pending on future shared library load? (y or [n])
Please answer y or [n].
Make breakpoint pending on future shared library load? (y or [n])
Please answer y or [n].
Make breakpoint pending on future shared library load? (y or [n])
Please answer y or [n].
Make breakpoint pending on future shared library load? (y or [n])
(gdb) b AAA::get
Can't find member of namespace, class, struct, or union named "AAA::get"
Hint: try 'AAA::get<TAB> or 'AAA::get<ESC-?>
(Note leading single quote.)
Make breakpoint pending on future shared library load? (y or [n])
Breakpoint 5 (AAA::get) pending.
(gdb) commands
Type commands for when breakpoint 5 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b DDD::DDD
Can't find member of namespace, class, struct, or union named "DDD::DDD"
Hint: try 'DDD::DDD<TAB> or 'DDD::DDD<ESC-?>
(Note leading single quote.)
Make breakpoint pending on future shared library load? (y or [n]) y
commBreakpoint 6 (DDD::DDD) pending.
(gdb) commands
Type commands for when breakpoint 6 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b DDD::get
Can't find member of namespace, class, struct, or union named "DDD::get"
Hint: try 'DDD::get<TAB> or 'DDD::get<ESC-?>
(Note leading single quote.)
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 7 (DDD::get) pending.
(gdb) commands
Type commands for when breakpoint 7 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b bbb1
Function "bbb1" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 8 (bbb1) pending.
(gdb) commands
Type commands for when breakpoint 8 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b CCC:CCC
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 9 (CCC:CCC) pending.
(gdb) commands
Type commands for when breakpoint 9 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
(gdb) b main
Breakpoint 10 at 0x8050c5a
(gdb) commands
Type commands for when breakpoint 10 is hit, one per line.
End with a line saying just "end".
>silent
>bt
>disassemble
>cont
>end
(gdb)
=
=
=
= Start running it
=
(gdb) r
Starting program: /export/home/bcpp/jfranzoy/tmp/d
[Thread debugging using libthread_db enabled]
[New Thread 1 (LWP 1)]
[Switching to Thread 1 (LWP 1)]
=
=
=
= 1st breakpoint fired in static initialization of c.cpp (c.so)
= it initialize ios_base and create global CCC object defined in c.cpp
=
#0 __static_initialization_and_destruction_0 (__initialize_p=1,
__priority=65535) at c.cpp:19
#1 0xfef70b80 in _GLOBAL__sub_I_c.cpp () at c.cpp:19
#2 0xfef70c5d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/c.so
#3 0xfef70c8a in _init () from /export/home/bcpp/jfranzoy/tmp/c.so
#4 0xfefce37e in call_init () from /usr/lib/ld.so.1
#5 0xfefcd7d5 in setup () from /usr/lib/ld.so.1
#6 0xfefdba3e in _setup () from /usr/lib/ld.so.1
#7 0xfefc299c in _rt_boot () from /usr/lib/ld.so.1
#8 0x08047648 in ?? ()
#9 0x08047774 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Dump of assembler code for function __static_initialization_and_destruction_0:
0xfef70b06 <+0>: push %ebp
0xfef70b07 <+1>: mov %esp,%ebp
0xfef70b09 <+3>: push %ebx
0xfef70b0a <+4>: sub $0x14,%esp
0xfef70b0d <+7>: call 0xfef70ba2
0xfef70b12 <+12>: add $0x101b6,%ebx
=> 0xfef70b18 <+18>: cmpl $0x1,0x8(%ebp)
0xfef70b1c <+22>: jne 0xfef70b43
<__static_initialization_and_destruction_0+61>
0xfef70b1e <+24>: cmpl $0xffff,0xc(%ebp)
0xfef70b25 <+31>: jne 0xfef70b43
<__static_initialization_and_destruction_0+61>
0xfef70b27 <+33>: lea 0x161(%ebx),%eax
0xfef70b2d <+39>: mov %eax,(%esp)
0xfef70b30 <+42>: call 0xfef70974 <std::ios_base::Init::Init()@plt>
0xfef70b35 <+47>: mov 0x24(%ebx),%eax
0xfef70b3b <+53>: mov %eax,(%esp)
0xfef70b3e <+56>: call 0xfef70984 <CCC::CCC()@plt>
0xfef70b43 <+61>: cmpl $0x0,0x8(%ebp)
0xfef70b47 <+65>: jne 0xfef70b60
<__static_initialization_and_destruction_0+90>
0xfef70b49 <+67>: cmpl $0xffff,0xc(%ebp)
0xfef70b50 <+74>: jne 0xfef70b60
<__static_initialization_and_destruction_0+90>
0xfef70b52 <+76>: lea 0x161(%ebx),%eax
0xfef70b58 <+82>: mov %eax,(%esp)
0xfef70b5b <+85>: call 0xfef70994 <std::ios_base::Init::~Init()@plt>
0xfef70b60 <+90>: add $0x14,%esp
0xfef70b63 <+93>: pop %ebx
0xfef70b64 <+94>: pop %ebp
0xfef70b65 <+95>: ret
End of assembler dump.
=
=
=
= 2nd breakpoint fired in static initialization of b.cpp
= It can be seen in the stack trace that this initialization is called
inside c.cpp (c.so) static initialization.
=
= It can be explained because CCC contructor calls bbb1() function
= which is defined in b.cpp (b.so)
=
= b.cpp static initialization just initialize ios_base
=
#0 __static_initialization_and_destruction_0 (__initialize_p=1,
__priority=65535) at b.cpp:9
#1 0xfef20e97 in _GLOBAL__sub_I_b.cpp () at b.cpp:9
#2 0xfef20f1d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/b.so
#3 0xfef20f4a in _init () from /export/home/bcpp/jfranzoy/tmp/b.so
#4 0xfefce37e in call_init () from /usr/lib/ld.so.1
#5 0xfefce1cf in is_dep_init () from /usr/lib/ld.so.1
#6 0xfefdaa4b in elf_bndr () from /usr/lib/ld.so.1
#7 0xfefc2ab4 in elf_rtbndr () from /usr/lib/ld.so.1
#8 0xfef90018 in ?? ()
#9 0xfef70b43 in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535) at c.cpp:19
#10 0xfef70b80 in _GLOBAL__sub_I_c.cpp () at c.cpp:19
#11 0xfef70c5d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/c.so
#12 0xfef70c8a in _init () from /export/home/bcpp/jfranzoy/tmp/c.so
#13 0xfefce37e in call_init () from /usr/lib/ld.so.1
#14 0xfefcd7d5 in setup () from /usr/lib/ld.so.1
#15 0xfefdba3e in _setup () from /usr/lib/ld.so.1
#16 0xfefc299c in _rt_boot () from /usr/lib/ld.so.1
#17 0x08047648 in ?? ()
#18 0x08047774 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Dump of assembler code for function __static_initialization_and_destruction_0:
0xfef20e2b <+0>: push %ebp
0xfef20e2c <+1>: mov %esp,%ebp
---Type <return> to continue, or q <return> to quit---
0xfef20e2e <+3>: push %ebx
0xfef20e2f <+4>: sub $0x14,%esp
0xfef20e32 <+7>: call 0xfef20eb9
0xfef20e37 <+12>: add $0x10141,%ebx
=> 0xfef20e3d <+18>: cmpl $0x1,0x8(%ebp)
0xfef20e41 <+22>: jne 0xfef20e5a
<__static_initialization_and_destruction_0+47>
0xfef20e43 <+24>: cmpl $0xffff,0xc(%ebp)
0xfef20e4a <+31>: jne 0xfef20e5a
<__static_initialization_and_destruction_0+47>
0xfef20e4c <+33>: lea 0x228(%ebx),%eax
0xfef20e52 <+39>: mov %eax,(%esp)
0xfef20e55 <+42>: call 0xfef20be0 <std::ios_base::Init::Init()@plt>
0xfef20e5a <+47>: cmpl $0x0,0x8(%ebp)
0xfef20e5e <+51>: jne 0xfef20e77
<__static_initialization_and_destruction_0+76>
0xfef20e60 <+53>: cmpl $0xffff,0xc(%ebp)
0xfef20e67 <+60>: jne 0xfef20e77
<__static_initialization_and_destruction_0+76>
0xfef20e69 <+62>: lea 0x228(%ebx),%eax
0xfef20e6f <+68>: mov %eax,(%esp)
0xfef20e72 <+71>: call 0xfef20bf0 <std::ios_base::Init::~Init()@plt>
0xfef20e77 <+76>: add $0x14,%esp
0xfef20e7a <+79>: pop %ebx
0xfef20e7b <+80>: pop %ebp
0xfef20e7c <+81>: ret
End of assembler dump.
=
=
=
= 3rd breakpoint fired in bbb1(). Called from CCC constructor inside
c.cpp (c.so) static initialization
=
= b.cpp (b.so) static initialization is already finished.
=
= bbb1() has a static AAA object. It calls __cxa_guard_acquire and
__cxa_guard_release in order to make
= this static object initialization thread safe, as c++11 mandates (as
far as I suppose).
=
#0 bbb1 (i=10) at b.cpp:6
#1 0xfef70bc5 in CCC (this=0xfef80e28) at c.cpp:15
#2 0xfef70b43 in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535) at c.cpp:19
#3 0xfef70b80 in _GLOBAL__sub_I_c.cpp () at c.cpp:19
#4 0xfef70c5d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/c.so
#5 0xfef70c8a in _init () from /export/home/bcpp/jfranzoy/tmp/c.so
#6 0xfefce37e in call_init () from /usr/lib/ld.so.1
#7 0xfefcd7d5 in setup () from /usr/lib/ld.so.1
#8 0xfefdba3e in _setup () from /usr/lib/ld.so.1
#9 0xfefc299c in _rt_boot () from /usr/lib/ld.so.1
#10 0x08047648 in ?? ()
#11 0x08047774 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Dump of assembler code for function bbb1(int):
0xfef20d3c <+0>: push %ebp
0xfef20d3d <+1>: mov %esp,%ebp
0xfef20d3f <+3>: push %edi
0xfef20d40 <+4>: push %esi
0xfef20d41 <+5>: push %ebx
0xfef20d42 <+6>: sub $0x1c,%esp
0xfef20d45 <+9>: call 0xfef20eb9
0xfef20d4a <+14>: add $0x1022e,%ebx
=> 0xfef20d50 <+20>: lea -0x1000a(%ebx),%eax
0xfef20d56 <+26>: mov %eax,0x4(%esp)
0xfef20d5a <+30>: mov 0x24(%ebx),%eax
0xfef20d60 <+36>: mov %eax,(%esp)
0xfef20d63 <+39>: call 0xfef20b40 <std::basic_ostream<char,
std::char_traits<char> >& std::operator<< <std::char_traits<char>
>(std::basic_ostream<char, std::char_traits<char> >&, char
const*)@plt>
0xfef20d68 <+44>: mov 0x8(%ebp),%edx
0xfef20d6b <+47>: mov %edx,0x4(%esp)
0xfef20d6f <+51>: mov %eax,(%esp)
0xfef20d72 <+54>: call 0xfef20b50 <std::basic_ostream<char,
std::char_traits<char> >::operator<<(int)@plt>
0xfef20d77 <+59>: lea -0x10004(%ebx),%edx
0xfef20d7d <+65>: mov %edx,0x4(%esp)
0xfef20d81 <+69>: mov %eax,(%esp)
0xfef20d84 <+72>: call 0xfef20b40 <std::basic_ostream<char,
std::char_traits<char> >& std::operator<< <std::char_traits<char>
>(std::basic_ostream<char, std::char_traits<char> >&, char
const*)@plt>
0xfef20d89 <+77>: mov 0x30(%ebx),%edx
0xfef20d8f <+83>: mov %edx,0x4(%esp)
0xfef20d93 <+87>: mov %eax,(%esp)
0xfef20d96 <+90>: call 0xfef20b60 <std::basic_ostream<char,
std::char_traits<char> >::operator<<(std::basic_ostream<char,
std::char_traits<char> >& (*)(std::basic_ostream<char,
std::char_traits<char> >&))@plt>
0xfef20d9b <+95>: lea 0x230(%ebx),%eax
0xfef20da1 <+101>: movzbl (%eax),%eax
0xfef20da4 <+104>: test %al,%al
---Type <return> to continue, or q <return> to quit---
0xfef20da6 <+106>: jne 0xfef20df5 <bbb1(int)+185>
0xfef20da8 <+108>: lea 0x230(%ebx),%eax
0xfef20dae <+114>: mov %eax,(%esp)
0xfef20db1 <+117>: call 0xfef20b70 <__cxa_guard_acquire@plt>
0xfef20db6 <+122>: test %eax,%eax
0xfef20db8 <+124>: setne %al
0xfef20dbb <+127>: test %al,%al
0xfef20dbd <+129>: je 0xfef20df5 <bbb1(int)+185>
0xfef20dbf <+131>: mov $0x0,%edi
0xfef20dc4 <+136>: mov 0x8(%ebp),%eax
0xfef20dc7 <+139>: mov %eax,0x4(%esp)
0xfef20dcb <+143>: lea 0x238(%ebx),%eax
0xfef20dd1 <+149>: mov %eax,(%esp)
0xfef20dd4 <+152>: call 0xfef20b80 <AAA::AAA(int)@plt>
0xfef20dd9 <+157>: lea 0x230(%ebx),%eax
0xfef20ddf <+163>: mov %eax,(%esp)
0xfef20de2 <+166>: call 0xfef20b90 <__cxa_guard_release@plt>
0xfef20de7 <+171>: lea -0x10262(%ebx),%eax
0xfef20ded <+177>: mov %eax,(%esp)
0xfef20df0 <+180>: call 0xfef20ba0 <atexit@plt>
0xfef20df5 <+185>: lea 0x238(%ebx),%eax
0xfef20dfb <+191>: mov %eax,(%esp)
0xfef20dfe <+194>: call 0xfef20bb0 <AAA::get() const@plt>
0xfef20e03 <+199>: add $0x1c,%esp
0xfef20e06 <+202>: pop %ebx
0xfef20e07 <+203>: pop %esi
0xfef20e08 <+204>: pop %edi
0xfef20e09 <+205>: pop %ebp
0xfef20e0a <+206>: ret
0xfef20e0b <+207>: mov %eax,%esi
0xfef20e0d <+209>: mov %edi,%eax
0xfef20e0f <+211>: test %al,%al
0xfef20e11 <+213>: jne 0xfef20e21 <bbb1(int)+229>
0xfef20e13 <+215>: lea 0x230(%ebx),%eax
0xfef20e19 <+221>: mov %eax,(%esp)
0xfef20e1c <+224>: call 0xfef20bc0 <__cxa_guard_abort@plt>
0xfef20e21 <+229>: mov %esi,%eax
0xfef20e23 <+231>: mov %eax,(%esp)
0xfef20e26 <+234>: call 0xfef20bd0 <_Unwind_Resume@plt>
End of assembler dump.
bbb1(10)
=
=
=
= 4th breakpoint fired in static initialization of a.cpp ??? Fired
from CCC constructor inside c.cpp (c.so) static initialization
=
= This is THE mistery from my ignorant point of view.
= Why is a.cpp static initialization called inside CCC ctor?
=
= a.cpp (a.so) static initialization may be called because bbb1 calls AAA ctor.
= But bbb1 isn't in call stack backtrace. Some gcc, ld or ld.so magic??
= May be that gdb is not showing the exact call stack?
=
= a.cpp static initialization creates a global DDD object whose
contructor calls bbb1() again
=
#0 __static_initialization_and_destruction_0 (__initialize_p=1,
__priority=65535) at a.cpp:25
#1 0xfef41026 in _GLOBAL__sub_I_a.cpp () at a.cpp:25
#2 0xfef4107d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/a.so
#3 0xfef410aa in _init () from /export/home/bcpp/jfranzoy/tmp/a.so
#4 0xfefce37e in call_init () from /usr/lib/ld.so.1
#5 0xfefce1cf in is_dep_init () from /usr/lib/ld.so.1
#6 0xfefdaa4b in elf_bndr () from /usr/lib/ld.so.1
#7 0xfefc2ab4 in elf_rtbndr () from /usr/lib/ld.so.1
#8 0xfef90980 in ?? ()
#9 0xfef70bc5 in CCC (this=0xfef80e28) at c.cpp:15
#10 0xfef70b43 in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535) at c.cpp:19
#11 0xfef70b80 in _GLOBAL__sub_I_c.cpp () at c.cpp:19
#12 0xfef70c5d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/c.so
#13 0xfef70c8a in _init () from /export/home/bcpp/jfranzoy/tmp/c.so
#14 0xfefce37e in call_init () from /usr/lib/ld.so.1
#15 0xfefcd7d5 in setup () from /usr/lib/ld.so.1
#16 0xfefdba3e in _setup () from /usr/lib/ld.so.1
#17 0xfefc299c in _rt_boot () from /usr/lib/ld.so.1
#18 0x08047648 in ?? ()
#19 0x08047774 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Dump of assembler code for function __static_initialization_and_destruction_0:
0xfef40fac <+0>: push %ebp
0xfef40fad <+1>: mov %esp,%ebp
0xfef40faf <+3>: push %ebx
---Type <return> to continue, or q <return> to quit---
0xfef40fb0 <+4>: sub $0x14,%esp
0xfef40fb3 <+7>: call 0xfef41048
0xfef40fb8 <+12>: add $0x10154,%ebx
=> 0xfef40fbe <+18>: cmpl $0x1,0x8(%ebp)
0xfef40fc2 <+22>: jne 0xfef40fe9
<__static_initialization_and_destruction_0+61>
0xfef40fc4 <+24>: cmpl $0xffff,0xc(%ebp)
0xfef40fcb <+31>: jne 0xfef40fe9
<__static_initialization_and_destruction_0+61>
0xfef40fcd <+33>: lea 0x238(%ebx),%eax
0xfef40fd3 <+39>: mov %eax,(%esp)
0xfef40fd6 <+42>: call 0xfef40c84 <std::ios_base::Init::Init()@plt>
0xfef40fdb <+47>: mov 0x58(%ebx),%eax
0xfef40fe1 <+53>: mov %eax,(%esp)
0xfef40fe4 <+56>: call 0xfef40c94 <DDD::DDD()@plt>
0xfef40fe9 <+61>: cmpl $0x0,0x8(%ebp)
0xfef40fed <+65>: jne 0xfef41006
<__static_initialization_and_destruction_0+90>
0xfef40fef <+67>: cmpl $0xffff,0xc(%ebp)
0xfef40ff6 <+74>: jne 0xfef41006
<__static_initialization_and_destruction_0+90>
0xfef40ff8 <+76>: lea 0x238(%ebx),%eax
0xfef40ffe <+82>: mov %eax,(%esp)
0xfef41001 <+85>: call 0xfef40ca4 <std::ios_base::Init::~Init()@plt>
0xfef41006 <+90>: add $0x14,%esp
0xfef41009 <+93>: pop %ebx
0xfef4100a <+94>: pop %ebp
0xfef4100b <+95>: ret
End of assembler dump.
=
=
=
= 5th breakpoint fired in bbb1. This is a reentrant call, which is not
supported by gcc for static
= variable initialization inside a function: it deadlocks
=
#0 bbb1 (i=10) at b.cpp:6
#1 0xfef40f35 in DDD (this=0xfef51340) at a.cpp:17
#2 0xfef40fe9 in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535) at a.cpp:25
#3 0xfef41026 in _GLOBAL__sub_I_a.cpp () at a.cpp:25
#4 0xfef4107d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/a.so
#5 0xfef410aa in _init () from /export/home/bcpp/jfranzoy/tmp/a.so
#6 0xfefce37e in call_init () from /usr/lib/ld.so.1
#7 0xfefce1cf in is_dep_init () from /usr/lib/ld.so.1
#8 0xfefdaa4b in elf_bndr () from /usr/lib/ld.so.1
#9 0xfefc2ab4 in elf_rtbndr () from /usr/lib/ld.so.1
#10 0xfef90980 in ?? ()
#11 0xfef70bc5 in CCC (this=0xfef80e28) at c.cpp:15
#12 0xfef70b43 in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535) at c.cpp:19
#13 0xfef70b80 in _GLOBAL__sub_I_c.cpp () at c.cpp:19
#14 0xfef70c5d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/c.so
#15 0xfef70c8a in _init () from /export/home/bcpp/jfranzoy/tmp/c.so
#16 0xfefce37e in call_init () from /usr/lib/ld.so.1
#17 0xfefcd7d5 in setup () from /usr/lib/ld.so.1
#18 0xfefdba3e in _setup () from /usr/lib/ld.so.1
#19 0xfefc299c in _rt_boot () from /usr/lib/ld.so.1
#20 0x08047648 in ?? ()
#21 0x08047774 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Dump of assembler code for function bbb1(int):
0xfef20d3c <+0>: push %ebp
0xfef20d3d <+1>: mov %esp,%ebp
0xfef20d3f <+3>: push %edi
0xfef20d40 <+4>: push %esi
0xfef20d41 <+5>: push %ebx
0xfef20d42 <+6>: sub $0x1c,%esp
0xfef20d45 <+9>: call 0xfef20eb9
0xfef20d4a <+14>: add $0x1022e,%ebx
=> 0xfef20d50 <+20>: lea -0x1000a(%ebx),%eax
0xfef20d56 <+26>: mov %eax,0x4(%esp)
0xfef20d5a <+30>: mov 0x24(%ebx),%eax
0xfef20d60 <+36>: mov %eax,(%esp)
0xfef20d63 <+39>: call 0xfef20b40 <std::basic_ostream<char,
std::char_traits<char> >& std::operator<< <std::char_traits<char>
>(std::basic_ostream<char, std::char_traits<char> >&, char
const*)@plt>
0xfef20d68 <+44>: mov 0x8(%ebp),%edx
0xfef20d6b <+47>: mov %edx,0x4(%esp)
0xfef20d6f <+51>: mov %eax,(%esp)
---Type <return> to continue, or q <return> to quit---
0xfef20d72 <+54>: call 0xfef20b50 <std::basic_ostream<char,
std::char_traits<char> >::operator<<(int)@plt>
0xfef20d77 <+59>: lea -0x10004(%ebx),%edx
0xfef20d7d <+65>: mov %edx,0x4(%esp)
0xfef20d81 <+69>: mov %eax,(%esp)
0xfef20d84 <+72>: call 0xfef20b40 <std::basic_ostream<char,
std::char_traits<char> >& std::operator<< <std::char_traits<char>
>(std::basic_ostream<char, std::char_traits<char> >&, char
const*)@plt>
0xfef20d89 <+77>: mov 0x30(%ebx),%edx
0xfef20d8f <+83>: mov %edx,0x4(%esp)
0xfef20d93 <+87>: mov %eax,(%esp)
0xfef20d96 <+90>: call 0xfef20b60 <std::basic_ostream<char,
std::char_traits<char> >::operator<<(std::basic_ostream<char,
std::char_traits<char> >& (*)(std::basic_ostream<char,
std::char_traits<char> >&))@plt>
0xfef20d9b <+95>: lea 0x230(%ebx),%eax
0xfef20da1 <+101>: movzbl (%eax),%eax
0xfef20da4 <+104>: test %al,%al
0xfef20da6 <+106>: jne 0xfef20df5 <bbb1(int)+185>
0xfef20da8 <+108>: lea 0x230(%ebx),%eax
0xfef20dae <+114>: mov %eax,(%esp)
0xfef20db1 <+117>: call 0xfef20b70 <__cxa_guard_acquire@plt>
0xfef20db6 <+122>: test %eax,%eax
0xfef20db8 <+124>: setne %al
0xfef20dbb <+127>: test %al,%al
0xfef20dbd <+129>: je 0xfef20df5 <bbb1(int)+185>
0xfef20dbf <+131>: mov $0x0,%edi
0xfef20dc4 <+136>: mov 0x8(%ebp),%eax
0xfef20dc7 <+139>: mov %eax,0x4(%esp)
0xfef20dcb <+143>: lea 0x238(%ebx),%eax
0xfef20dd1 <+149>: mov %eax,(%esp)
0xfef20dd4 <+152>: call 0xfef20b80 <AAA::AAA(int)@plt>
0xfef20dd9 <+157>: lea 0x230(%ebx),%eax
0xfef20ddf <+163>: mov %eax,(%esp)
0xfef20de2 <+166>: call 0xfef20b90 <__cxa_guard_release@plt>
0xfef20de7 <+171>: lea -0x10262(%ebx),%eax
0xfef20ded <+177>: mov %eax,(%esp)
0xfef20df0 <+180>: call 0xfef20ba0 <atexit@plt>
0xfef20df5 <+185>: lea 0x238(%ebx),%eax
0xfef20dfb <+191>: mov %eax,(%esp)
0xfef20dfe <+194>: call 0xfef20bb0 <AAA::get() const@plt>
0xfef20e03 <+199>: add $0x1c,%esp
0xfef20e06 <+202>: pop %ebx
0xfef20e07 <+203>: pop %esi
0xfef20e08 <+204>: pop %edi
0xfef20e09 <+205>: pop %ebp
0xfef20e0a <+206>: ret
0xfef20e0b <+207>: mov %eax,%esi
0xfef20e0d <+209>: mov %edi,%eax
0xfef20e0f <+211>: test %al,%al
0xfef20e11 <+213>: jne 0xfef20e21 <bbb1(int)+229>
0xfef20e13 <+215>: lea 0x230(%ebx),%eax
0xfef20e19 <+221>: mov %eax,(%esp)
0xfef20e1c <+224>: call 0xfef20bc0 <__cxa_guard_abort@plt>
0xfef20e21 <+229>: mov %esi,%eax
0xfef20e23 <+231>: mov %eax,(%esp)
0xfef20e26 <+234>: call 0xfef20bd0 <_Unwind_Resume@plt>
End of assembler dump.
bbb1(10)
=
=
=
= program hangs here
=
=
=
= I stopped debugging using ctrl-c
=
^C
Program received signal SIGINT, Interrupt.
0xfece9019 in __lwp_park () from /lib/libc.so.1
=
=
=
= A call stack backtrace shows the deadlock, but do not shows the
reentrant call to bbb1
=
(gdb) bt
#0 0xfece9019 in __lwp_park () from /lib/libc.so.1
#1 0xfece365e in cond_sleep_queue () from /lib/libc.so.1
#2 0xfece3817 in cond_wait_queue () from /lib/libc.so.1
#3 0xfece3b94 in cond_wait_common () from /lib/libc.so.1
#4 0xfece3d02 in _cond_wait () from /lib/libc.so.1
#5 0xfece3d2d in cond_wait () from /lib/libc.so.1
#6 0xfece3d66 in pthread_cond_wait () from /lib/libc.so.1
#7 0xfeed2898 in __gthread_cond_wait (g=0xfef311a8) at
/export/home/bcpp/mlevalle/work/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=0xfef311a8) at
/export/home/bcpp/mlevalle/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=0xfef311a8) at
/export/home/bcpp/mlevalle/work/build-gcc/out/i386-pc-solaris2.10/libstdc++-v3/include/ext/concurrence.h:377
#10 __cxa_guard_acquire (g=0xfef311a8) at
../../../../src/gcc-4.6.2/libstdc++-v3/libsupc++/guard.cc:289
#11 0xfef20db6 in bbb1 (i=10) at b.cpp:7
#12 0xfef40f35 in DDD (this=0xfef51340) at a.cpp:17
#13 0xfef40fe9 in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535) at a.cpp:25
#14 0xfef41026 in _GLOBAL__sub_I_a.cpp () at a.cpp:25
#15 0xfef4107d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/a.so
#16 0xfef410aa in _init () from /export/home/bcpp/jfranzoy/tmp/a.so
#17 0xfefce37e in call_init () from /usr/lib/ld.so.1
#18 0xfefce1cf in is_dep_init () from /usr/lib/ld.so.1
#19 0xfefdaa4b in elf_bndr () from /usr/lib/ld.so.1
#20 0xfefc2ab4 in elf_rtbndr () from /usr/lib/ld.so.1
#21 0xfef90980 in ?? ()
#22 0xfef70bc5 in CCC (this=0xfef80e28) at c.cpp:15
#23 0xfef70b43 in __static_initialization_and_destruction_0
(__initialize_p=1, __priority=65535) at c.cpp:19
#24 0xfef70b80 in _GLOBAL__sub_I_c.cpp () at c.cpp:19
#25 0xfef70c5d in __do_global_ctors_aux () from
/export/home/bcpp/jfranzoy/tmp/c.so
#26 0xfef70c8a in _init () from /export/home/bcpp/jfranzoy/tmp/c.so
#27 0xfefce37e in call_init () from /usr/lib/ld.so.1
#28 0xfefcd7d5 in setup () from /usr/lib/ld.so.1
#29 0xfefdba3e in _setup () from /usr/lib/ld.so.1
#30 0xfefc299c in _rt_boot () from /usr/lib/ld.so.1
#31 0x08047648 in ?? ()
#32 0x08047774 in ?? ()
=
=
=
= there is two threads
=
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) info threads
* 2 Thread 1 0xfece9019 in __lwp_park () from /lib/libc.so.1
1 LWP 1 0xfece9019 in __lwp_park () from /lib/libc.so.1
=
=
=
= kill the program and stop the debugger
=
(gdb) kill
Kill the program being debugged? (y or n) y
(gdb) q
solaris10:~/jfranzoy/tmp>
Thans: Juan Carlos Franzoy
More information about the Gcc-help
mailing list