From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12948 invoked by alias); 30 May 2011 19:12:46 -0000 Received: (qmail 12937 invoked by uid 22791); 30 May 2011 19:12:45 -0000 X-SWARE-Spam-Status: No, hits=-0.8 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RFC_ABUSE_POST,TW_RG,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from nm28.bullet.mail.bf1.yahoo.com (HELO nm28.bullet.mail.bf1.yahoo.com) (98.139.212.187) by sourceware.org (qpsmtpd/0.43rc1) with SMTP; Mon, 30 May 2011 19:12:25 +0000 Received: from [98.139.212.151] by nm28.bullet.mail.bf1.yahoo.com with NNFMP; 30 May 2011 19:12:24 -0000 Received: from [98.139.212.249] by tm8.bullet.mail.bf1.yahoo.com with NNFMP; 30 May 2011 19:12:24 -0000 Received: from [127.0.0.1] by omp1058.mail.bf1.yahoo.com with NNFMP; 30 May 2011 19:12:24 -0000 Received: (qmail 2857 invoked by uid 60001); 30 May 2011 19:12:24 -0000 Message-ID: <520738.2569.qm@web161012.mail.bf1.yahoo.com> Received: from [96.250.194.147] by web161012.mail.bf1.yahoo.com via HTTP; Mon, 30 May 2011 12:12:24 PDT Date: Mon, 30 May 2011 23:10:00 -0000 From: Pavel Tolkachev Reply-To: paulTolk@yahoo.com Subject: Re: dlclose() doesn't unload any .so that uses Boost To: gcc-help@gcc.gnu.org, J In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org X-SW-Source: 2011-05/txt/msg00431.txt.bz2 --- On Sun, 5/29/11, J wrote: > From: J > Subject: dlclose() doesn't unload any .so that uses Boost > To: gcc-help@gcc.gnu.org > Date: Sunday, May 29, 2011, 3:32 AM > Hi. >=20 > 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: >=20 > // host.cpp > // compile with: g++ -ldl host.cpp -o host > #include > #include >=20 > int main( int argc, char ** argv ) > { > =A0 =A0 printf( "host: Loading libchild.so...\n" ); > =A0 =A0 void * so =3D dlopen( "./libchild.so", > RTLD_LOCAL | RTLD_NOW ); > =A0 =A0 printf( "host: so =3D %p\n", so ); >=20 > =A0 =A0 if( so =3D=3D 0 ) return 1; >=20 > =A0 =A0 printf( "host: Unloading libchild.so...\n" > ); > =A0 =A0 if( dlclose( so ) !=3D 0 ) > =A0 =A0 { > =A0 =A0 =A0 =A0 printf( "host: Error: %s\n", > dlerror() ); > =A0 =A0 =A0 =A0 return 1; > =A0 =A0 } > =A0 =A0 printf( "host: Unloaded.\n" ); > =A0 =A0 printf( "host: %p\n", dlopen( > "./libchild.so", RTLD_NOLOAD ) ); >=20 > =A0 =A0 return 0; > } >=20 > // child.cpp > // compile with: g++ -lboost_signals child.cpp -shared > -fPIC -o libchild.so > #include > #include >=20 > struct foobar_t > { > =A0 =A0 boost :: signal< void () > signal; > }; >=20 > void=A0 __attribute__ ( ( constructor ) ) ctor() > { > =A0 =A0 foobar_t foobar; >=20 > =A0 =A0 printf( "child: Constructor\n" ); > } >=20 > void=A0 __attribute__ ( ( destructor ) ) dtor() > { > =A0 =A0 printf( "child: Destructor\n" ); > } >=20 >=20 > This is the output I get: >=20 > host: Loading libchild.so... > child: Constructor > host: so =3D 0x94b6020 > host: Unloading libchild.so... > host: Unloaded. > host: (nil) > child: Destructor >=20 > As you can see, dlclose() doesn't properly unload the .so, > even though > it claims that it has done so.=20 It actually doesn't. It just confirms there were one or more references cou= nts to the library and it decreased their count by 1 (see man dlclose). I t= hink you can achieve same effect by defining any global object with non-tri= vial destructor in the library, not necessarily a boost::signal.=20 On remediation side, if you are comfortable with the client code's explicit= ly calling dlclose() anyway, why don't you allocate your signal object in f= ree storage via operator new and call something like MyDlclose() (or childC= lose()) instead of it where you would first delete this object (and all oth= ers 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: >=20 > boost :: signal< void () > signal; >=20 > it works properly: >=20 > host: Loading libchild.so... > child: Constructor > host: so =3D 0x8f6f020 > host: Unloading libchild.so... > child: Destructor > host: Unloaded. > host: (nil) >=20 > 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. >=20 > Thanks. >=20 Hope this helps, -Pavel