Using _fini() with dlclose() - Unix

This is a discussion on Using _fini() with dlclose() - Unix ; Hi In the linux man page for the dl*() functions it states: If the dynamic library exports a routine named _fini, then that routine is called just before the library is unloaded. However if I put that function in my ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: Using _fini() with dlclose()

  1. Using _fini() with dlclose()

    Hi

    In the linux man page for the dl*() functions it states:

    If the dynamic library exports a routine named _fini, then that
    routine is
    called just before the library is unloaded.

    However if I put that function in my shared object code I get the
    following error:

    /tmp/ccHXNzCm.o(.text+0x0): In function `_fini':
    /home/robertnb/source/factory/dynobj.cpp:25: multiple definition of
    `_fini'
    /usr/lib/crti.o(.fini+0x0): first defined here
    collect2: ld returned 1 exit status

    Is the man page wrong or am I doing something wrong? I've tried
    defining _fini() as void _fini() and
    int _fini() but it makes no difference.

    B2003


  2. Re: Using _fini() with dlclose()

    Boltar writes:

    >In the linux man page for the dl*() functions it states:


    > If the dynamic library exports a routine named _fini, then that
    >routine is
    > called just before the library is unloaded.


    >However if I put that function in my shared object code I get the
    >following error:


    >/tmp/ccHXNzCm.o(.text+0x0): In function `_fini':
    >/home/robertnb/source/factory/dynobj.cpp:25: multiple definition of
    >`_fini'
    >/usr/lib/crti.o(.fini+0x0): first defined here
    >collect2: ld returned 1 exit status



    How are you linking the library?

    While it is technically correct that _init() and _fini() are called when
    a library are loaded, what really is supposed to happen is that the
    different .o objects export .init and .fini sections which are then
    concatenated into _init() and _fini() functions.

    This is typically done through the linker starting the link command line
    with an object crti.o which contains

    _init() {
    _fini() {

    in the appropriate sections (.init, .fini) and end the link phase with
    crtn.o which contains:
    }
    }

    for each section.

    In order to call your own functions in _init() or _fini() you should use:


    int myinit() __attribute__ ((constructor));
    int myfini() __attribute__ ((destructor));


    (Or, if you use Sun's compiler which are now also available under Linux, you'd
    use:

    #pragma init(myinit)
    #pragma fini(myfini)


    Casper
    --
    Expressed in this posting are my opinions. They are in no way related
    to opinions held by my employer, Sun Microsystems.
    Statements on Sun products included here are not gospel and may
    be fiction rather than truth.

  3. Re: Using _fini() with dlclose()

    On Nov 6, 1:38 pm, Casper H.S. Dik wrote:
    > How are you linking the library?


    I'm using -shared for the .so and -ldl -rdynamic for the module that
    loads it.

    > int myinit() __attribute__ ((constructor));
    > int myfini() __attribute__ ((destructor));


    Didn't compile:

    dynobj.cpp:31: error: attributes are not allowed on a function-
    definition

    B2003


  4. Re: Using _fini() with dlclose()

    Boltar wrote:
    > On Nov 6, 1:38 pm, Casper H.S. Dik wrote:
    >> How are you linking the library?

    >
    > I'm using -shared for the .so and -ldl -rdynamic for the module that
    > loads it.
    >
    >> int myinit() __attribute__ ((constructor));
    >> int myfini() __attribute__ ((destructor));

    >
    > Didn't compile:
    >
    > dynobj.cpp:31: error: attributes are not allowed on a function-
    > definition
    >
    > B2003
    >

    The attribute keyword has to be used on a prototype
    (http://ocliteracy.com/techtips/gnu-c-attributes.html), the error
    indicates you used it on the function itself. In other words you have
    to do it this way:


    int myfini() __attribute__ ((destructor));

    int myfini()
    {
    // do stuff
    }

    hth

  5. Re: Using _fini() with dlclose()

    On Nov 6, 2:26 pm, Jim Marshall
    wrote:
    > The attribute keyword has to be used on a prototype
    > (http://ocliteracy.com/techtips/gnu-c-attributes.html), the error
    > indicates you used it on the function itself. In other words you have
    > to do it this way:
    >
    > int myfini() __attribute__ ((destructor));
    >
    > int myfini()
    > {
    > // do stuff
    >
    > }


    Thanks , that worked. Is it gcc specific though?

    B2003



  6. Re: Using _fini() with dlclose()

    Boltar wrote:
    > On Nov 6, 2:26 pm, Jim Marshall
    > wrote:
    >> The attribute keyword has to be used on a prototype
    >> (http://ocliteracy.com/techtips/gnu-c-attributes.html), the error
    >> indicates you used it on the function itself. In other words you have
    >> to do it this way:
    >>
    >> int myfini() __attribute__ ((destructor));
    >>
    >> int myfini()
    >> {
    >> // do stuff
    >>
    >> }

    >
    > Thanks , that worked. Is it gcc specific though?

    yes it is. But you can stub __attribute__ out on non-GNU compilers tho:

    #ifndef __GNUC__
    #define __attribute__(x) /* do nothing */
    #endif /* __GNUC__ */

    -Jim
    >
    > B2003
    >
    >


  7. Re: Using _fini() with dlclose()

    On Nov 6, 8:32 am, Boltar wrote:
    > On Nov 6, 2:26 pm, Jim Marshall
    > wrote:
    >
    > > The attribute keyword has to be used on a prototype
    > > (http://ocliteracy.com/techtips/gnu-c-attributes.html), the error
    > > indicates you used it on the function itself. In other words you have
    > > to do it this way:

    >
    > > int myfini() __attribute__ ((destructor));

    >
    > > int myfini()
    > > {
    > > // do stuff

    >
    > > }

    >
    > Thanks , that worked. Is it gcc specific though?


    Yes. But since it looks like you're using C++, you can also define
    some static object in your shared library, and its destructor will be
    called. (gcc's attribute is really just a way to give C access to the
    constructor/destructor calling mechanisms.) This should also be more
    portable.

    Example:

    class myclass {
    public:
    myclass::myclass ();
    myclass::~myclass ();
    };

    myclass::myclass () {
    // do initialization for library
    }

    myclass::~myclass () {
    // do cleanup for library
    }

    static myclass myclassobj;

    Actually, object-oriented design would probably dictate that all your
    initialization and cleanup be in constructors and destructors for
    existing classes, so in that case everything would just work.


+ Reply to Thread