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

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

 



--- On Sun, 5/29/11, J <j@xxxxxxxxxx> wrote:

> From: J <j@xxxxxxxxxx>
> Subject: dlclose() doesn't unload any .so that uses Boost
> To: gcc-help@xxxxxxxxxxx
> Date: Sunday, May 29, 2011, 3:32 AM
> Hi.
> 
> First, I would like to apologize if this isn't in any way
> related to
> GCC, however I don't know anywhere else where I can turn
> to. Please
> consider the following code:
> 
> // host.cpp
> // compile with: g++ -ldl host.cpp -o host
> #include <stdio.h>
> #include <dlfcn.h>
> 
> int main( int argc, char ** argv )
> {
>     printf( "host: Loading libchild.so...\n" );
>     void * so = dlopen( "./libchild.so",
> RTLD_LOCAL | RTLD_NOW );
>     printf( "host: so = %p\n", so );
> 
>     if( so == 0 ) return 1;
> 
>     printf( "host: Unloading libchild.so...\n"
> );
>     if( dlclose( so ) != 0 )
>     {
>         printf( "host: Error: %s\n",
> dlerror() );
>         return 1;
>     }
>     printf( "host: Unloaded.\n" );
>     printf( "host: %p\n", dlopen(
> "./libchild.so", RTLD_NOLOAD ) );
> 
>     return 0;
> }
> 
> // child.cpp
> // compile with: g++ -lboost_signals child.cpp -shared
> -fPIC -o libchild.so
> #include <stdio.h>
> #include <boost/signals.hpp>
> 
> struct foobar_t
> {
>     boost :: signal< void () > signal;
> };
> 
> void  __attribute__ ( ( constructor ) ) ctor()
> {
>     foobar_t foobar;
> 
>     printf( "child: Constructor\n" );
> }
> 
> void  __attribute__ ( ( destructor ) ) dtor()
> {
>     printf( "child: Destructor\n" );
> }
> 
> 
> This is the output I get:
> 
> host: Loading libchild.so...
> child: Constructor
> host: so = 0x94b6020
> host: Unloading libchild.so...
> host: Unloaded.
> host: (nil)
> child: Destructor
> 
> As you can see, dlclose() doesn't properly unload the .so,
> even though
> it claims that it has done so. 
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). I think you can achieve same effect by defining any global object with non-trivial destructor in the library, not necessarily a boost::signal. 

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.


> If you'll remove this line:
> 
> boost :: signal< void () > signal;
> 
> it works properly:
> 
> host: Loading libchild.so...
> child: Constructor
> host: so = 0x8f6f020
> host: Unloading libchild.so...
> child: Destructor
> host: Unloaded.
> host: (nil)
> 
> It took me a while to track this down. Now, my question is
> - is this a
> bug? If so, in what? In GCC? (I tried this with both 4.5
> and 4.6) In
> the dynamic linker? In Boost? If not - why? And how would I
> fix this?
> Any insight in greatly appreciated.
> 
> Thanks.
> 

Hope this helps,
-Pavel




[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