Bug 24189 - crash at exit after dlclose with -fuse-cxa-atexit
Summary: crash at exit after dlclose with -fuse-cxa-atexit
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.4
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-04 13:40 UTC by Petr Ovtchenkov
Modified: 2005-11-27 17:40 UTC (History)
3 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments
testcase (843 bytes, application/x-tar)
2005-10-04 13:49 UTC, Petr Ovtchenkov
Details
__cxa_atexit and __cxa_finalize that work correctly (1.22 KB, text/plain)
2005-11-27 16:48 UTC, Petr Ovtchenkov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Petr Ovtchenkov 2005-10-04 13:40:49 UTC
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
Comment 1 Andrew Pinski 2005-10-04 13:48:32 UTC
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.
Comment 2 Petr Ovtchenkov 2005-10-04 13:49:17 UTC
Created attachment 9870 [details]
testcase

Unpack, (cd dlclose-cxa; x.sh). Script (bash) x.sh compile and run test; crash at exit.
Comment 3 Andrew Pinski 2005-10-04 13:52:18 UTC
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
Comment 4 Petr Ovtchenkov 2005-10-04 13:54:28 UTC
> What is the version of glibc you have?  I have 2.3.3.

2.2.5
Comment 5 Andrew Pinski 2005-10-04 13:55:14 UTC
(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.
Comment 6 Petr Ovtchenkov 2005-10-04 14:04:02 UTC
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
Comment 7 Petr Ovtchenkov 2005-10-04 14:17:11 UTC
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.
Comment 8 Andrew Pinski 2005-10-04 14:34:32 UTC
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
Comment 9 Andrew Pinski 2005-10-04 14:36:16 UTC
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
Comment 10 Petr Ovtchenkov 2005-10-04 15:49:00 UTC
Like my.
Comment 11 Petr Ovtchenkov 2005-10-04 15:55:54 UTC
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.
Comment 12 Petr Ovtchenkov 2005-10-06 11:28:55 UTC
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?
Comment 13 Petr Ovtchenkov 2005-11-27 16:41:14 UTC
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?
Comment 14 Petr Ovtchenkov 2005-11-27 16:48:19 UTC
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.
Comment 15 Andrew Pinski 2005-11-27 16:52:14 UTC
(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.
Comment 16 Petr Ovtchenkov 2005-11-27 17:40:29 UTC
Thanks for explanation. Link to this issue: http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor (for archive/reference purposes).