This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


On Mon, May 30, 2011 at 9:12 PM, Pavel Tolkachev <paultolk@yahoo.com> 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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]