Program open DSO with dlopen; DSO has has any C++ global (static) object; program close DSO with dlclose; crash at program exit. Compiler use -fuse-cxa-atexit option, compiler was builded as Reading specs from /opt/gcc-3.4.4/lib/gcc/i686-pc-linux-gnu/3.4.4/specs Configured with: ./configure --enable-__cxa_atexit --enable-threads --with-system-zlib --enable-languages=c,c++,java --prefix=/opt/gcc-3.4.4 Thread model: posix gcc version 3.4.4 Possible crash reason: call of dtor of static object in DSO after DSO was unloaded. Test: > cat test.cc #include <dlfcn.h> //#include <iostream> //#include <iomanip> //using namespace std; typedef void *(*func_type)(); int main() { void *lh = dlopen( "./libtestg.so", RTLD_LAZY ); //cerr << hex << (unsigned)lh << dec << endl; func_type f = (func_type)dlsym( lh, "func" ); f(); dlclose( lh ); return 0; } > cat testlib.cc //#include <iostream> //using namespace std; extern "C" void func(); class A { public: A(); ~A(); private: char *p; }; A::A() { /* p = new char [50]; */ } A::~A() { /* delete [] p; */ } static A a; // <- crash at call cxa_atexit after dlclose? //static char b[30]; void func() { // A a; //a = new A; // cerr << "Hello\n"; } > cat x.sh #!/bin/bash CXX=c++ ${CXX} -pthread -fexceptions -fident -g -fuse-cxa-atexit -c -o test.o test.cc ${CXX} -pthread -fexceptions -fident -g -fuse-cxa-atexit -nostdlib -o test `for o in crt{1,i,begin}.o; do ${CXX} -print-file-name=\$o; done` test.o -lsupc++ -ldl -lgcc_s -lpthread -lc -lm `for o in crt{end,n}.o; do ${CXX} -print-file-name=\$o; done` ${CXX} -pthread -fexceptions -fident -fPIC -g -fuse-cxa-atexit -c -o testlib.o testlib.cc ${CXX} -pthread -fexceptions -fident -fPIC -g -fuse-cxa-atexit -shared -Wl,-hlibtestg.so.0.0 -nostdlib -o libtestg.so.0.0.0 `for o in crt{i,beginS}.o; do ${CXX} -print-file-name=\$o; done` testlib.o -lgcc_s -lsupc++ -lpthread -lc -lm `for o in crt{endS,n}.o; do ${CXX} -print-file-name=\$o; done` rm -f libtestg.so.0.0; ln -s libtestg.so.0.0.0 libtestg.so.0.0; rm -f libtestg.so.0; ln -s libtestg.so.0.0 libtestg.so.0; rm -f libtestg.so; ln -s libtestg.so.0 libtestg.so ./test
This works for me with: + c++ -pthread -fexceptions -fident -g -fuse-cxa-atexit -c -o test.o test.cc + c++ -pthread -fexceptions -fident -g -fuse-cxa-atexit -o test test.o -ldl + c++ -pthread -fexceptions -fident -fPIC -g -fuse-cxa-atexit -c -o testlib.o testlib.cc + c++ -pthread -fexceptions -fident -fPIC -g -fuse-cxa-atexit -shared -Wl,-hlibtestg.so.0.0 -o libtestg.so.0.0.0 testlib.o -ldl + rm -f libtestg.so.0.0 + ln -s libtestg.so.0.0.0 libtestg.so.0.0 + rm -f libtestg.so.0 + ln -s libtestg.so.0.0 libtestg.so.0 + rm -f libtestg.so + ln -s libtestg.so.0 libtestg.so + ./test What is the version of glibc you have? I have 2.3.3.
Created attachment 9870 [details] testcase Unpack, (cd dlclose-cxa; x.sh). Script (bash) x.sh compile and run test; crash at exit.
It works with your script too: sh -x x.sh + CXX=/home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ + /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -pthread -fexceptions -fident -g -fuse-cxa-atexit -c -o test.o test.cc ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crt1.o ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crti.o ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crtbegin.o ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crtend.o ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crtn.o + /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -pthread -fexceptions -fident -g -fuse-cxa-atexit -nostdlib -o test /usr/lib/crt1.o /usr/lib/crti.o /home/gates/pinskia/ia32_linux_gcc3_4/lib/gcc/i686-pc-linux-gnu/3.4.0/crtbegin.o test.o -lsupc++ -ldl -lgcc_s -lpthread -lc -lm /home/gates/pinskia/ia32_linux_gcc3_4/lib/gcc/i686-pc-linux-gnu/3.4.0/crtend.o /usr/lib/crtn.o + /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -pthread -fexceptions -fident -fPIC -g -fuse-cxa-atexit -c -o testlib.o testlib.cc ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crti.o ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crtbeginS.o ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crtendS.o ++ /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -print-file-name=crtn.o + /home/peshtigo/pinskia/ia32_linux_gcc3_4/bin/c++ -pthread -fexceptions -fident -fPIC -g -fuse-cxa-atexit -shared -Wl,-hlibtestg.so.0.0 -nostdlib -o libtestg.so.0.0.0 /usr/lib/crti.o /home/gates/pinskia/ia32_linux_gcc3_4/lib/gcc/i686-pc-linux-gnu/3.4.0/crtbeginS.o testlib.o -lgcc_s -lsupc++ -lpthread -lc -lm /home/gates/pinskia/ia32_linux_gcc3_4/lib/gcc/i686-pc-linux-gnu/3.4.0/crtendS.o /usr/lib/crtn.o + rm -f libtestg.so.0.0 + ln -s libtestg.so.0.0.0 libtestg.so.0.0 + rm -f libtestg.so.0 + ln -s libtestg.so.0.0 libtestg.so.0 + rm -f libtestg.so + ln -s libtestg.so.0 libtestg.so + ./test
> What is the version of glibc you have? I have 2.3.3. 2.2.5
(In reply to comment #4) > > What is the version of glibc you have? I have 2.3.3. > > 2.2.5 This sounds like a bug in your glibc then.
May be. Just for info: Debian GNU/Linux 3.0 ('woody'), Linux peak 2.6.12.5 #1 SMP Mon Aug 29 17:22:33 MSD 2005 i686 unknown
But may be this is problem in crtbeginS.o or crtendS.o? I.e. in something like __cxa_finalize: > nm /opt/gcc-3.4.4/lib/gcc/i686-pc-linux-gnu/3.4.4/crtbeginS.o U _GLOBAL_OFFSET_TABLE_ w _Jv_RegisterClasses 00000000 ? __CTOR_LIST__ 00000000 ? __DTOR_LIST__ 00000000 ? __JCR_LIST__ w __cxa_finalize 00000000 t __do_global_dtors_aux 00000000 D __dso_handle 00000000 b completed.1 00000060 t frame_dummy 00000000 d p.0 > nm /opt/gcc-3.4.4/lib/gcc/i686-pc-linux-gnu/3.4.4/crtendS.o U _GLOBAL_OFFSET_TABLE_ 00000000 ? __CTOR_END__ 00000000 ? __DTOR_END__ 00000000 ? __FRAME_END__ 00000000 ? __JCR_END__ 00000000 t __do_global_ctors_aux BTW, due to access to free memory the result may be SIGFAULT or not.
Here is the output I have for those files in 3.4.0: earth:~>nm ~/ia32_linux_gcc3_4/lib/gcc/i686-pc-linux-gnu/3.4.0/crtendS.o 00000000 d __CTOR_END__ 00000000 t __do_global_ctors_aux 00000000 d __DTOR_END__ 00000000 r __FRAME_END__ U _GLOBAL_OFFSET_TABLE_ 00000000 T __i686.get_pc_thunk.bx 00000000 d __JCR_END__ earth:~>nm ~/ia32_linux_gcc3_4/lib/gcc/i686-pc-linux-gnu/3.4.0/crtbeginS.o 00000000 b completed.1 00000000 d __CTOR_LIST__ w __cxa_finalize 00000000 t __do_global_dtors_aux 00000000 D __dso_handle 00000000 d __DTOR_LIST__ 00000060 t frame_dummy U _GLOBAL_OFFSET_TABLE_ 00000000 T __i686.get_pc_thunk.bx 00000000 d __JCR_LIST__ w _Jv_RegisterClasses 00000000 d p.0
And how I configured GCC: earth:~>~/ia32_linux_gcc3_4/bin/gcc -v Reading specs from /home/gates/pinskia/ia32_linux_gcc3_4/lib/gcc/i686-pc-linux-gnu/3.4.0/specs Configured with: ../configure --prefix=/home/gates/pinskia/ia32_linux_gcc3_4 --enable-__cxa_atexit Thread model: posix gcc version 3.4.0
Like my.
Sometimes test run fine fror me too, but (the same build and same evironment!) sometimes not. This like depends upon garbage... Well, as expected---call of dtor of died object.
Really, I wonder why code specific for C++ language support should be in glibc? What about platforms without glibc? May be code to call dtors should be in crtbegin/crtbeginS?
This is really bug in glibc: __cxa_finalize don't call all registered handlers in case of NULL argument (glibc 2.2.5 has this bug, but 2.3.2 already not). But nevertheless, the problem still present at platforms without glibc. Really, I wonder why code specific for C++ language support (and even more: specific for gcc) should be in glibc? May be the better place is one of crt*.o?
Created attachment 10348 [details] __cxa_atexit and __cxa_finalize that work correctly cxa.c contain code with __cxa_atexit and __cxa_finalize that work correctly with gcc 3.4.x (really I am check only 3.4.4). Useful when builded as so library and used in LD_PRELOAD to fix glibc problem.
(In reply to comment #13) > Really, I wonder why code specific for C++ language support (and even more: > specific for gcc) should be in glibc? May be the better place is one of crt*.o? It is not specific to GCC, it is a standard C++ ABI defined by a committee (and across multiple compilers now), it is the IA64 C++ ABI which is used by more than GCC and on more than just IA64. Anyways this is a bug in glibc.
Thanks for explanation. Link to this issue: http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor (for archive/reference purposes).