Re: c++ static initialization question

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux