__cxa_atexit and __cxa_finalize implementation

Peter S. Mazinger ps.m at gmx.net
Fri Sep 16 13:17:10 UTC 2005


On Fri, 16 Sep 2005, Stephen Warren wrote:

> Peter S. Mazinger wrote:
> > On Sun, 11 Sep 2005, Stephen Warren wrote:
> >>Stephen Warren wrote:
> >>>Here's a fixed version of my patch to implement these functions.
> >>
> >>Did anyone have any feedback on this? Is it likely to get merged, or are 
> >>there problems with it?
> > 
> > I have rebuilt a gentoo base development system applying this cxa_atexit 
> > patch to uclibc and using --enable-cxa_atexit to build gcc. I can't see 
> > until now any problems, but it would be good to have some test scenario 
> > or app that is known to fail.
> 
> Here's part 1 of a couple tests that demonstrate the problems.
> 
> It's a little involved, but hopefully not too hard to follow, since not 
> all the details are relevant.
> 
> Basically, there's a global "CNvMutex g_mutex". The constructor for this 
> global will run before main, and the destructor after main.
> 
> The constructor calls function INvThreading::GetImp, which contains a 
> static data member g_nvt, which gets constructed when 
> INvThreading::GetImp is called.
> 
> Now, the CNvMutex constructor logically depends upon the g_nvt 
> constructor, because it essentially calls it. The compiler/code "knows" 
> (or should know) this because at run-time, the g_nvt constructor 
> completes before the g_mutex constructor.
> 
> What is supposed to happen (by "spec" - although not sure what spec!) is 
> that because of this dependency, the g_nvt destructor is deferred until 
> after the g_mutex destructor is run, at app exit time.
> 
> However, with -fno-use-cxa-atexit compile flag (or the equivalent gcc 
> build flag that sets this as a default), the gcc-generated code for the 
> global constructors does not implement this ordering, and hence g_nvt is 
> destructed first, then the g_mutex destructor calls a method on g_nvt, 
> and the app crashes with a pure virtual method call.
> 
> Building with -fuse-cxa-atexit (or gcc build-time equivalent) will fix 
> this, since the generated global ctor/dtor management code is very 
> different. However, this requires that the C lib implement __cxa_atexit, 
> hence my original patch.
> 
> To demonstrate the problem, one should run these commands (note, I did 
> this with the regular Fedora Core 3 glibc toolchain, since that's what I 
> have at hand and in a known state right now, but the errors were the 
> same with a non __cxa_atexit uClibc toolchain)
> 
> BAD:
> g++ -fno-use-cxa-atexit -o invt invt.cpp && ./invt
> CNvMutex::CNvMutex init list pre m_pThreading
> INvThreading::GetImp pre
> CNvThreadingImp::CNvThreadingImp
> INvThreading::GetImp post
> CNvMutex::CNvMutex init list post m_pThreading
> CNvMutex::CNvMutex
> CNvThreadingImp::Create->10
> CNvMutex::CNvMutex -> m_h=10
> CNvMutex::Func()
> CNvThreadingImp::~CNvThreadingImp
> CNvMutex::~CNvMutex (m_h=10) start

building against uClibc++ produces the same without the next to lines
these seem to be comments from libstdc++ (Aborted is there)
> pure virtual method called
> terminate called without an active exception
> Aborted
> 
libstdc++ is exactly as you wrote

> GOOD:
> g++ -fuse-cxa-atexit -o invt invt.cpp && ./invt
> CNvMutex::CNvMutex init list pre m_pThreading
> INvThreading::GetImp pre
> CNvThreadingImp::CNvThreadingImp
> INvThreading::GetImp post
> CNvMutex::CNvMutex init list post m_pThreading
> CNvMutex::CNvMutex
> CNvThreadingImp::Create->10
> CNvMutex::CNvMutex -> m_h=10
> CNvMutex::Func()
> CNvMutex::~CNvMutex (m_h=10) start
> CNvThreadingImp::Destroy(10)
> CNvMutex::~CNvMutex (m_h=10) done
> CNvThreadingImp::~CNvThreadingImp

both uClibc++ and libstdc++ perform like this

tested natively on uClibc-svn-20050908 w/ your cxa patch (and my addons 
for nonshared) gcc-3.4.4/binutils-2.16.91.0.3

apropos: typo: s/old_atexit.c/old_atexit.o/ needed in my last patch 
(old_atexit compatibility)

Peter
> 
> Hope this helps!
> 
> Test part 2 (to come later) demonstrates issues with DSOs being 
> unloaded; dtors for objects in the DSO must run at DSO unload time 
> rather than app exit time. This is why the __cxa_atexit implementation 
> must play with __dso_handle, rather than just calling atexit() - which 
> would fix the above problem.
> 
> 

-- 
Peter S. Mazinger <ps dot m at gmx dot net>           ID: 0xA5F059F2
Key fingerprint = 92A4 31E1 56BC 3D5A 2D08  BB6E C389 975E A5F0 59F2




More information about the uClibc mailing list