--- 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. >