public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* dlclose() doesn't unload any .so that uses Boost
@ 2011-05-30 23:07 J
  2011-05-31 10:18 ` Alan Modra
  0 siblings, 1 reply; 4+ messages in thread
From: J @ 2011-05-30 23:07 UTC (permalink / raw)
  To: binutils

Hi.

I've been told on the GCC mailing list to ask here. 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. 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.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: dlclose() doesn't unload any .so that uses Boost
  2011-05-30 23:07 dlclose() doesn't unload any .so that uses Boost J
@ 2011-05-31 10:18 ` Alan Modra
  2011-05-31 12:38   ` J
  0 siblings, 1 reply; 4+ messages in thread
From: Alan Modra @ 2011-05-31 10:18 UTC (permalink / raw)
  To: J; +Cc: binutils

On Mon, May 30, 2011 at 03:18:52PM +0200, J wrote:
> As you can see, dlclose() doesn't properly unload the .so, even though
> it claims that it has done so. If you'll remove this line:
> 
> boost :: signal< void () > signal;
> 
> it works properly:

On x86 with gcc-4.4.3, ld 2.21.51.20110509, glibc 2.11.1, libboost
1.40.0 I get
host: Loading libchild.so...
child: Constructor
host: so = 0x8240020
host: Unloading libchild.so...
child: Destructor
host: Unloaded.
host: (nil)

ie. the same result as your "works properly".  My guess would be that
your version of glibc handles dlclose differently to mine.  Note that
there are quite legitimate reasons that dlclose might not behave
as you expect, eg. if libchild.so was built with DF_1_NODELETE set.
That probably isn't the case here, but worth checking with readelf
whether that flag is set for libchild.so and any of its dependencies.

"LD_DEBUG=files ./host" for me shows (in part)

     26306:	calling init: ./libchild.so
     26306:	
child: Constructor
     26306:	opening file=./libchild.so [0]; direct_opencount=1
     26306:	
host: so = 0x9a86020
host: Unloading libchild.so...
     26306:	
     26306:	calling fini: ./libchild.so [0]
     26306:	
child: Destructor
     26306:	
     26306:	calling fini: /usr/lib/libboost_signals.so.1.40.0 [0]
     26306:	
     26306:	
     26306:	file=./libchild.so [0];  destroying link map
     26306:	
     26306:	file=/usr/lib/libboost_signals.so.1.40.0 [0];  destroying link map
host: Unloaded.
host: (nil)
     26306:	
     26306:	calling fini: ./host [0]

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: dlclose() doesn't unload any .so that uses Boost
  2011-05-31 10:18 ` Alan Modra
@ 2011-05-31 12:38   ` J
  2011-05-31 14:04     ` Jakub Jelinek
  0 siblings, 1 reply; 4+ messages in thread
From: J @ 2011-05-31 12:38 UTC (permalink / raw)
  To: J, binutils

On Tue, May 31, 2011 at 7:43 AM, Alan Modra <amodra@gmail.com> wrote:
> On Mon, May 30, 2011 at 03:18:52PM +0200, J wrote:
>> As you can see, dlclose() doesn't properly unload the .so, even though
>> it claims that it has done so. If you'll remove this line:
>>
>> boost :: signal< void () > signal;
>>
>> it works properly:
>
> On x86 with gcc-4.4.3, ld 2.21.51.20110509, glibc 2.11.1, libboost
> 1.40.0 I get
> host: Loading libchild.so...
> child: Constructor
> host: so = 0x8240020
> host: Unloading libchild.so...
> child: Destructor
> host: Unloaded.
> host: (nil)
>
> ie. the same result as your "works properly".  My guess would be that
> your version of glibc handles dlclose differently to mine.  Note that
> there are quite legitimate reasons that dlclose might not behave
> as you expect, eg. if libchild.so was built with DF_1_NODELETE set.
> That probably isn't the case here, but worth checking with readelf
> whether that flag is set for libchild.so and any of its dependencies.

I've managed to track this issue down. It looks like a bug in GCC:

$ g++-4.4 -lboost_signals child.cc -shared -fPIC -o libchild.so
$ ./host
host: Loading libchild.so...
child: Constructor
host: so = 0x85ab020
host: Unloading libchild.so...
child: Destructor
host: Unloaded.
host: (nil)

$ g++-4.6 -lboost_signals child.cc -shared -fPIC -o libchild.so
$ ./host
host: Loading libchild.so...
child: Constructor
host: so = 0x8b34020
host: Unloading libchild.so...
host: Unloaded.
host: (nil)
child: Destructor

Thanks for your help anyway. (:

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: dlclose() doesn't unload any .so that uses Boost
  2011-05-31 12:38   ` J
@ 2011-05-31 14:04     ` Jakub Jelinek
  0 siblings, 0 replies; 4+ messages in thread
From: Jakub Jelinek @ 2011-05-31 14:04 UTC (permalink / raw)
  To: J; +Cc: binutils

On Tue, May 31, 2011 at 08:43:45AM +0200, J wrote:
> I've managed to track this issue down. It looks like a bug in GCC:

Most likely the difference is just that g++-4.6 emits STB_GNU_UNIQUE
symbols while g++-4.4 doesn't.  And, when any STB_GNU_UNIQUE symbols
are resolved against some library, it is marked as nodelete.
Therefore, NOTABUG.

	Jakub

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-05-31 10:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-30 23:07 dlclose() doesn't unload any .so that uses Boost J
2011-05-31 10:18 ` Alan Modra
2011-05-31 12:38   ` J
2011-05-31 14:04     ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).