This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: at exit alternative for AIX


On Aug 5, 2012, at 3:50 PM, Perry Smith wrote:

> 
> On Aug 5, 2012, at 1:09 PM, David Edelsohn wrote:
> 
>> On Sun, Aug 5, 2012 at 9:56 AM, Perry Smith <pedzsan@gmail.com> wrote:
>> 
>>> I was planning on exploring when _GLOBAL__FD was called today.  I
>>> need to figure out when gcc puts the call to the dtor in _GLOBAL__FD
>>> path rather than in the atexit path.  The net implies that "static" uses
>>> atexit while a global non-static uses _GLOBAL__FD
>>> 
>>> I'm also exploring what it would take to port a version of GNU's
>>> __cxa_atexit to AIX.  I think after I figure out when various dtors
>>> get called, I should be able to figure out if / how to do that.
>>> 
>>> Part of my confusion / concern is "why have two methods?"
>>> Does the spec say that dtors much be called at different times?
>> 
>> Destructors are added to _GLOBAL__FD by collect2 at link time.  It
>> scans the object files for destructor functions, sorts them by
>> priority and creates a function connected to _GLOBAL__FD to call them.
>> Collect2 performs the same grouping for constructors, creates a
>> function and connects it to _GLOBAL__FI.  The uniquely named functions
>> are added to the AIX linker command line as arguments to the
>> -binitfini option to establish them as initializer/finalizer functions
>> for the shared object.
>> 
>> AIX does not have a ctor/dtor or init/fini section in object files,
>> nor _cxa_atexit.
>> 
>> AIX dlclose() should call AIX terminateAndUnload() service that will
>> call the fini routine registered by -binitfini.  If something else in
>> GCC is trying to register the termination function for systems without
>> _cxa_atexit() using atexit(), it probably is conflicting and trying to
>> run the destructors twice.
>> 
>> Another difference between AIX and SVR4 is AIX invokes init and fini
>> functions for multiple, dependent shared objects breadth first, while
>> SVR4 invokes them depth first based on library dependencies.  There is
>> an old Bugzilla entry with a proposal to push init functions onto a
>> stack as they are seen when libraries are loaded and then run them in
>> SVR4 dependency order.
> 
> Thank you both for helping.
> 
> I understand when atexit is used.  I believe the _GLOBAL__FD method
> could be used instead and would be more correct but it somehow needs to
> be conditionalized.
> 
> To get the atexit to be used, you need a function that returns a static
> that is declared inside the function.  In my code below, this is
> "func".
> 
> The function registered with atexit is called tcf_0 (I'm sure that
> would increment if there are more than one).  I mention that hoping it
> might help in tracking down where it is being created.
> 
> There are other parts to this program that I left because, to me, it
> was interesting when atexit is called and all the places where it is
> not called.
> 
> I call the program x1.cpp.  x1 with no argument does not create
> "func".  x1 with an argument does.  Note that if func is not created,
> the dtor is not called (which seems obvoius but that is where the
> difficulty is going to come from).
> 
> My thoughts on how to solve this would call tcf_0 from the _GLOBAL_FD
> and have tcf_0 check a flag.  If not set, it does nothing.  In the
> special ctor where atexit is now being called, just set that flag
> instead of calling atexit.
> 
> Here is the program:
> 
> #include <iostream>
> using namespace std;
> 
> class foo {
> private:
>    const char *name;
>    void mess(const char *s) {
>        cout << s << " " << name << endl;
>    }
> 
> public:
>    foo(const char *s) {
>        name = s;
>        mess("ctor");
>    }
> 
>    ~foo() {
>        mess("dtor");
>    }
> };
> 
> class bar {
>    static foo surf;
> };
> foo bar::surf("bar");
> 
> foo g("global");
> static foo s("static");
> 
> foo& func()
> {
>    static foo val("func");
>    return val;
> }
> 
> int main (int argc, char *argv[])
> {
>    cout << "Hello World!" << endl;
>    foo a("auto");
> 
>    if (argc > 1)
>        foo &f = func();
> 
>    cout << "Good Bye World!" << endl;
>    return 0;
> }
> 
> Output with x1 called with no argument:
> ctor bar
> ctor global
> ctor static
> Hello World!
> ctor auto
> Good Bye World!
> dtor auto
> dtor static
> dtor global
> dtor bar
> 
> Output with x1 called with an argument:
> ctor bar
> ctor global
> ctor static
> Hello World!
> ctor auto
> ctor func << atexit called just after this prints.
> Good Bye World!
> dtor auto
> dtor func
> dtor static
> dtor global
> dtor bar
> 
> I'm happy to create a bug report if anyone wants me to.

Not sure why this thread died.  I've been looking at the code trying to gain
the courage to try and implement the changes I suggested but was 
also waiting to hear back from others.

Thank you,
Perry


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]