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