Re: dlclose() doesn't unload any .so that uses Boost

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




--- On Mon, 5/30/11, J <j@xxxxxxxxxx> wrote:

> From: J <j@xxxxxxxxxx>
> Subject: Re: dlclose() doesn't unload any .so that uses Boost
> To: paulTolk@xxxxxxxxx
> Cc: gcc-help@xxxxxxxxxxx
> Date: Monday, May 30, 2011, 11:56 PM
> On Mon, May 30, 2011 at 9:12 PM,
> Pavel Tolkachev <paultolk@xxxxxxxxx>
> wrote:
> > It actually doesn't. It just confirms there were one
> or more references counts to the library and it decreased
> their count by 1 (see man dlclose).
> 
> Yes, I've read man dlclose:
> 
> "If the same library is loaded again with dlopen(), the
> same file
> handle is returned. The dl library maintains reference
> counts for
> library handles, so a dynamic library is not deallocated
> until
> dlclose() has been called on it as many times as dlopen()
> has
> succeeded on it."

> 
> I'm only calling dlopen() once and boost doesn't call
> dlopen() at all,
> so following this manpage my dlclose() should close the
> library. If
> the refcount can be increased by something else then maybe
> this
> manpage needs updating?
> 
> Besides, RTLD_NOLOAD paragraph states this:
> 
> "This can be used to test if the library is already
> resident (dlopen()
> returns NULL if it is not, or the library's handle if it
> is
> resident)."
> 
> While library is clearly still resident dlopen( RTLD_NOLOAD
> ) returns
> NULL; another bug either in the code or in the manpage.
> 
> > On remediation side, if you are comfortable with the
> client code's explicitly calling dlclose() anyway, why don't
> you allocate your signal object in free storage via operator
> new and call something like MyDlclose() (or childClose())
> instead of it where you would first delete this object (and
> all others of the kind) and then call dlclose()? This won't
> increase the degree of client code cooperation needed to use
> your library.
> 
> Unfortunately, this doesn't work, e.g. this is enough to
> make a .so
> impossible unload:
> 
> delete ( new boost :: signal< void () > );
> 
> Oh and, I've just noticed that this code doesn't really
> even have to
> run. Consider:
> 
> // child.cpp
> // compile with: g++ -lboost_signals child.cpp -shared
> -fPIC -o libchild.so
> #include <stdio.h>
> #include <boost/signals.hpp>
> 
> void  __attribute__ ( ( constructor ) ) ctor()
> {
>    printf( "child: Constructor\n" );
> }
> 
> void  __attribute__ ( ( destructor ) ) dtor()
> {
>    printf( "child: Destructor\n" );
> }
> 
> void a_function_that_does_not_get_called()
> {
>     new boost :: signal< void () >();
> }
> 
> The result:
> 
> host: Loading libchild.so...
> child: Constructor
> host: so = 0x8938020
> host: Unloading libchild.so...
> host: Unloaded.
> host: (nil)
> child: Destructor
> 
> This pretty much looks like a bug to me.
I admit I spoke too soon, assumed before actually trying your code. After I have tried (both 1st and 2nd versions), the code gave different output to me:

host: Loading libchild.so...
child: Constructor
host: so = 0x8db4020
host: Unloading libchild.so...
child: Destructor
host: Unloaded.
host: (nil)

Which seems correct (dlclose() calls the dtor()). I used 
gcc version 4.4.5
libdl-2.12.1.so
boost 1.45.0
Linux kernel 2.6.35-28
libc-2.12.1.so

Hope this helps,
-Pavel


> 
> Thanks.
>



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux