Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Nov 2010 11:00:22 GMT
From:      Kostik Belousov <kostikbel@gmail.com>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: misc/151861: dlclose() of library causes separately opened libraries to unload as well
Message-ID:  <201011031100.oA3B0Md4062873@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR misc/151861; it has been noted by GNATS.

From: Kostik Belousov <kostikbel@gmail.com>
To: Jaakko Heinonen <jh@freebsd.org>
Cc: Arjan van Leeuwen <freebsd-maintainer@opera.com>, bug-followup@freebsd.org,
        kan@freebsd.org
Subject: Re: misc/151861: dlclose() of library causes separately opened libraries to unload as well
Date: Wed, 3 Nov 2010 12:54:29 +0200

 --b2N6ngaUR9vV44n2
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Wed, Nov 03, 2010 at 12:06:49PM +0200, Jaakko Heinonen wrote:
 > On 2010-11-02, Kostik Belousov wrote:
 > > Why do you think that your patch is not correct ?
 >=20
 > Well, I didn't say that I think it's incorrect. :)
 >=20
 > > I feel that more explicit handling of the state of the DAG is cleaner.
 >=20
 > I don't disagree but there is a problem with your patch. If an object
 > has the DF_1_NODELETE flag set, dag is initialized in
 > load_needed_objects(). In this case the reference count isn't correctly
 > bumped in dlopen() because dag_inited is already set.
 Seems you are right. See that patch below.
 It changes init_dag() to unconditionally increment refcount.
 
 >=20
 > (BTW. I think that there shouldn't be the ref_dag(obj1) call in
 > load_needed_objects(). Now the reference count is increased twice in the
 > nodelete case.)
 With init_dag() incrementing the refcount unconditionally, the ref_dag()
 indeed can be removed.
 
 >=20
 > > --- a/libexec/rtld-elf/rtld.c
 > > +++ b/libexec/rtld-elf/rtld.c
 > > @@ -1275,8 +1275,11 @@ init_dag(Obj_Entry *root)
 > >  {
 > >      DoneList donelist;
 > > =20
 > > +    if (root->dag_inited)
 > > +	    return;
 >=20
 > Why init_dag() should be allowed to be called multiple times for an
 > object?
 
 If already loaded object is dlopened, dlclosed, and then again dlopened,
 init_dag() will be called twice, one time for each dlopen.
 
 diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
 index f1ffc3e..f75ee35 100644
 --- a/libexec/rtld-elf/rtld.c
 +++ b/libexec/rtld-elf/rtld.c
 @@ -1275,11 +1275,12 @@ init_dag(Obj_Entry *root)
  {
      DoneList donelist;
 =20
 -    if (root->dag_inited)
 -	    return;
 -    donelist_init(&donelist);
 -    init_dag1(root, root, &donelist);
 -    root->dag_inited =3D true;
 +    if (!root->dag_inited) {
 +	donelist_init(&donelist);
 +	init_dag1(root, root, &donelist);
 +	root->dag_inited =3D true;
 +    }
 +    ref_dag(root);
  }
 =20
  static void
 @@ -1290,7 +1291,6 @@ init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *=
 dlp)
      if (donelist_check(dlp, obj))
  	return;
 =20
 -    obj->refcount++;
      objlist_push_tail(&obj->dldags, root);
      objlist_push_tail(&root->dagmembers, obj);
      for (needed =3D obj->needed;  needed !=3D NULL;  needed =3D needed->ne=
 xt)
 @@ -1438,7 +1438,6 @@ load_needed_objects(Obj_Entry *first, int flags)
  	    if (obj1 !=3D NULL && obj1->z_nodelete && !obj1->ref_nodel) {
  		dbg("obj %s nodelete", obj1->path);
  		init_dag(obj1);
 -		ref_dag(obj1);
  		obj1->ref_nodel =3D true;
  	    }
  	}
 @@ -2054,10 +2053,7 @@ dlopen(const char *name, int mode)
  	     * already loaded as a dependency, initialize the dag
  	     * starting at it.
  	     */
 -	    if (obj->dl_refcount =3D=3D 1)
 -		init_dag(obj);
 -	    else
 -		ref_dag(obj);
 +	    init_dag(obj);
 =20
  	    if (ld_tracing)
  		goto trace;
 
 --b2N6ngaUR9vV44n2
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (FreeBSD)
 
 iEYEARECAAYFAkzRP2QACgkQC3+MBN1Mb4hlxQCfVo6OyCtfOu/iMiG444ql0rP8
 dT4An2sqpVM/mqJbwYnw2vJoopDqvqqC
 =rUZc
 -----END PGP SIGNATURE-----
 
 --b2N6ngaUR9vV44n2--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201011031100.oA3B0Md4062873>