From freebsd-maintainer@opera.com  Mon Nov  1 12:19:57 2010
Return-Path: <freebsd-maintainer@opera.com>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 722E51065673
	for <FreeBSD-gnats-submit@freebsd.org>; Mon,  1 Nov 2010 12:19:57 +0000 (UTC)
	(envelope-from freebsd-maintainer@opera.com)
Received: from smtp.opera.com (smtp.opera.com [213.236.208.81])
	by mx1.freebsd.org (Postfix) with ESMTP id 00AC58FC0C
	for <FreeBSD-gnats-submit@freebsd.org>; Mon,  1 Nov 2010 12:19:56 +0000 (UTC)
Received: from arjanl.oslo.osa (sgw-oslo2.opera.com [213.236.208.46])
	(authenticated bits=0)
	by smtp.opera.com (8.14.3/8.14.3/Debian-5+lenny1) with ESMTP id oA1C9G4J025015
	(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT)
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 1 Nov 2010 12:09:22 GMT
Message-Id: <1288613378.2621@arjanl.oslo.osa>
Date: Mon, 1 Nov 2010 13:09:38 +0100
From: "Arjan van Leeuwen" <freebsd-maintainer@opera.com>
To: "FreeBSD gnats submit" <FreeBSD-gnats-submit@freebsd.org>
Subject: dlclose() of library causes separately opened libraries to unload as well
X-Send-Pr-Version: gtk-send-pr 0.4.9 
X-GNATS-Notify:

>Number:         151861
>Category:       kern
>Synopsis:       [rtld] dlclose() of library causes separately opened libraries to unload as well
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Nov 01 12:20:11 UTC 2010
>Closed-Date:    Wed Oct 12 14:46:13 UTC 2011
>Last-Modified:  Wed Oct 12 14:46:13 UTC 2011
>Originator:     Arjan van Leeuwen
>Release:        FreeBSD 8.1-RELEASE amd64
>Organization:
Opera Software ASA 
>Environment:


System: FreeBSD 8.1-RELEASE #0: Mon Jul 19 02:36:49 UTC 2010
    root@mason.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC



>Description:


Assume we have a library liba.so, containing a function a(), and a library libb.so, containing function b(). liba.so needs functionality from libb.so, so liba.so links in libb.so.

An application doesn't know about the relation between these libraries, but needs to call a() and b(). It dlopen()s libb.so and obtains a pointer to b(), and it dlopen()s liba.so and obtains a pointer to a().

As soon as the application doesn't need a() anymore, it dlclose()s liba.so.

Expected result: the pointer to b() is still valid and can be called
Actual result: the pointer to b() has become invalid, even though the application did not dlclose() the handle to libb.so. On calling b(), the application crashes with a segmentation fault.

Note: this bug is the cause of a FreeBSD-specific crash in Opera (ports/150117).


>How-To-Repeat:


Extract the attached shar archive and execute 'make test'.

This will cause a crash on FreeBSD, and will print 'success' on Linux.


>Fix:


--- dlopentest.sh begins here ---
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	dlopentest
#	dlopentest/Makefile
#	dlopentest/a.h
#	dlopentest/a.c
#	dlopentest/b.h
#	dlopentest/b.c
#	dlopentest/main.c
#
echo c - dlopentest
mkdir -p dlopentest > /dev/null 2>&1
echo x - dlopentest/Makefile
sed 's/^X//' >dlopentest/Makefile << '2075fca623562c5bd8776415e7b01bf6'
Xall: dlopentest liba.so
X
Xlibb.so: b.c
X	gcc -g -fPIC -shared -o libb.so b.c
X
Xliba.so: libb.so a.c
X	gcc -g -L. -fPIC -shared -lb -o liba.so a.c
X
Xdlopentest: main.c
X	gcc -g -o dlopentest main.c
X
Xclean:
X	rm -f dlopentest liba.so libb.so
X
Xtest: all
X	LD_LIBRARY_PATH=. ./dlopentest
2075fca623562c5bd8776415e7b01bf6
echo x - dlopentest/a.h
sed 's/^X//' >dlopentest/a.h << 'fc414acea66cdc81629a88bfee826a11'
Xconst char* a();
fc414acea66cdc81629a88bfee826a11
echo x - dlopentest/a.c
sed 's/^X//' >dlopentest/a.c << '0ad10ab266ed1f8ba3b38758bb80e7f7'
X#include "a.h"
X#include "b.h"
X
Xconst char* a()
X{
X  return b();
X}
0ad10ab266ed1f8ba3b38758bb80e7f7
echo x - dlopentest/b.h
sed 's/^X//' >dlopentest/b.h << '318c19e5810f4ba86fe6f909829d72e7'
Xconst char* b();
318c19e5810f4ba86fe6f909829d72e7
echo x - dlopentest/b.c
sed 's/^X//' >dlopentest/b.c << 'f9fa01da76fe4015102bc9a5d0c22c09'
X#include "b.h"
X
Xconst char* b()
X{
X  return "b";
X}
f9fa01da76fe4015102bc9a5d0c22c09
echo x - dlopentest/main.c
sed 's/^X//' >dlopentest/main.c << 'a3b6e3077e820f950e38c9b3614efead'
X#include <stdio.h>
X#include <dlfcn.h>
X#include <stdlib.h>
X
Xvoid* LoadLibrary(const char* library)
X{
X  void* handle = dlopen(library, RTLD_LAZY);
X  if (!handle)
X  {
X	fprintf(stderr, "can't load %s: %s\n", library, dlerror());
X	exit(1);
X  }
X  return handle;
X}
X
Xvoid* LoadFunction(void* handle, const char* function)
X{
X  void* fptr = dlsym(handle, function);
X  if (!fptr)
X  {
X	fprintf(stderr, "can't resolve function %s: %s\n", function, dlerror());
X	exit(1);
X  }
X  return fptr;
X}
X
Xint main(int argc, char* argv[])
X{
X  void* handle_a = LoadLibrary("liba.so");
X  const char* (*a)() = LoadFunction(handle_a, "a");
X
X  printf("from a: %s\n", a());
X
X  void* handle_b = LoadLibrary("libb.so");
X  const char* (*b)() = LoadFunction(handle_b, "b");
X
X  printf("from b: %s\n", b());
X
X  dlclose(handle_a);
X
X  printf("from b after dlclosing a: %s\n", b());
X
X  dlclose(handle_b);
X
X  printf("success\n");
X
X  return 0;
X}
a3b6e3077e820f950e38c9b3614efead
exit

--- dlopentest.sh ends here ---



>Release-Note:
>Audit-Trail:

From: Jaakko Heinonen <jh@FreeBSD.org>
To: Arjan van Leeuwen <freebsd-maintainer@opera.com>
Cc: bug-followup@FreeBSD.org, kan@FreeBSD.org, kib@FreeBSD.org
Subject: Re: misc/151861: dlclose() of library causes separately opened
 libraries to unload as well
Date: Tue, 2 Nov 2010 19:36:54 +0200

 On 2010-11-01, Arjan van Leeuwen wrote:
 > Assume we have a library liba.so, containing a function a(), and a
 > library libb.so, containing function b(). liba.so needs functionality
 > from libb.so, so liba.so links in libb.so.
 > 
 > An application doesn't know about the relation between these
 > libraries, but needs to call a() and b(). It dlopen()s libb.so and
 > obtains a pointer to b(), and it dlopen()s liba.so and obtains a
 > pointer to a().
 > 
 > As soon as the application doesn't need a() anymore, it dlclose()s
 > liba.so.
 > 
 > Expected result: the pointer to b() is still valid and can be called
 > Actual result: the pointer to b() has become invalid, even though the
 > application did not dlclose() the handle to libb.so. On calling b(),
 > the application crashes with a segmentation fault.
 > 
 > Extract the attached shar archive and execute 'make test'.
 
 Thank you for providing the test case.
 
 > This will cause a crash on FreeBSD, and will print 'success' on Linux.
 
 There is a problem with reference counting in dlopen(). If an object has
 been loaded by load_needed_objects() its dagmembers list may be empty
 after loading. If the list is empty, the ref_dag() call done for already
 loaded objects in dlopen() doesn't have effect.
 
 Here is a patch to demonstrate the problem. The test passes with the
 patch applied.
 
 %%%
 Index: libexec/rtld-elf/rtld.c
 ===================================================================
 --- libexec/rtld-elf/rtld.c	(revision 214676)
 +++ libexec/rtld-elf/rtld.c	(working copy)
 @@ -2046,7 +2046,10 @@ dlopen(const char *name, int mode)
  	} else {
  
  	    /* Bump the reference counts for objects on this DAG. */
 -	    ref_dag(obj);
 +	    if (STAILQ_EMPTY(&obj->dagmembers))
 +		init_dag(obj);
 +	    else
 +		ref_dag(obj);
  
  	    if (ld_tracing)
  		goto trace;
 %%%
 
 I have cc'd kan@ and kib@. Do you have ideas how to fix this correctly?
 
 -- 
 Jaakko

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: Tue, 2 Nov 2010 22:13:06 +0200

 --kQl6KHw6oLQq4hVK
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Tue, Nov 02, 2010 at 07:36:54PM +0200, Jaakko Heinonen wrote:
 > On 2010-11-01, Arjan van Leeuwen wrote:
 > > Assume we have a library liba.so, containing a function a(), and a
 > > library libb.so, containing function b(). liba.so needs functionality
 > > from libb.so, so liba.so links in libb.so.
 > >=20
 > > An application doesn't know about the relation between these
 > > libraries, but needs to call a() and b(). It dlopen()s libb.so and
 > > obtains a pointer to b(), and it dlopen()s liba.so and obtains a
 > > pointer to a().
 > >=20
 > > As soon as the application doesn't need a() anymore, it dlclose()s
 > > liba.so.
 > >=20
 > > Expected result: the pointer to b() is still valid and can be called
 > > Actual result: the pointer to b() has become invalid, even though the
 > > application did not dlclose() the handle to libb.so. On calling b(),
 > > the application crashes with a segmentation fault.
 > >=20
 > > Extract the attached shar archive and execute 'make test'.
 >=20
 > Thank you for providing the test case.
 >=20
 > > This will cause a crash on FreeBSD, and will print 'success' on Linux.
 >=20
 > There is a problem with reference counting in dlopen(). If an object has
 > been loaded by load_needed_objects() its dagmembers list may be empty
 > after loading. If the list is empty, the ref_dag() call done for already
 > loaded objects in dlopen() doesn't have effect.
 >=20
 > Here is a patch to demonstrate the problem. The test passes with the
 > patch applied.
 >=20
 > %%%
 > Index: libexec/rtld-elf/rtld.c
 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 > --- libexec/rtld-elf/rtld.c	(revision 214676)
 > +++ libexec/rtld-elf/rtld.c	(working copy)
 > @@ -2046,7 +2046,10 @@ dlopen(const char *name, int mode)
 >  	} else {
 > =20
 >  	    /* Bump the reference counts for objects on this DAG. */
 > -	    ref_dag(obj);
 > +	    if (STAILQ_EMPTY(&obj->dagmembers))
 > +		init_dag(obj);
 > +	    else
 > +		ref_dag(obj);
 > =20
 >  	    if (ld_tracing)
 >  		goto trace;
 > %%%
 >=20
 > I have cc'd kan@ and kib@. Do you have ideas how to fix this correctly?
 
 Why do you think that your patch is not correct ?
 I feel that more explicit handling of the state of the DAG is cleaner.
 
 diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
 index 8bc8692..f1ffc3e 100644
 --- 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;
      donelist_init(&donelist);
      init_dag1(root, root, &donelist);
 +    root->dag_inited =3D true;
  }
 =20
  static void
 @@ -2045,8 +2048,16 @@ dlopen(const char *name, int mode)
  	    }
  	} else {
 =20
 -	    /* Bump the reference counts for objects on this DAG. */
 -	    ref_dag(obj);
 +	    /*
 +	     * Bump the reference counts for objects on this DAG.  If
 +	     * this is the first dlopen() call for the object that was
 +	     * 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);
 =20
  	    if (ld_tracing)
  		goto trace;
 diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
 index 6bae2f0..faa84e2 100644
 --- a/libexec/rtld-elf/rtld.h
 +++ b/libexec/rtld-elf/rtld.h
 @@ -222,6 +222,7 @@ typedef struct Struct_Obj_Entry {
      bool ref_nodel : 1;		/* Refcount increased to prevent dlclose */
      bool init_scanned: 1;	/* Object is already on init list. */
      bool on_fini_list: 1;	/* Object is already on fini list. */
 +    bool dag_inited : 1;	/* Object has its DAG initialized. */
 =20
      struct link_map linkmap;	/* For GDB and dlinfo() */
      Objlist dldags;		/* Object belongs to these dlopened DAGs (%) */
 
 --kQl6KHw6oLQq4hVK
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (FreeBSD)
 
 iEYEARECAAYFAkzQcNEACgkQC3+MBN1Mb4jABgCg7KYATJ1CUDLOwOPHYufcx3P6
 lXEAnjRvZPn3H1yYOZnFO9htGSIFywnj
 =Kfrv
 -----END PGP SIGNATURE-----
 
 --kQl6KHw6oLQq4hVK--

From: Alexander Kabaev <kabaev@gmail.com>
To: Kostik Belousov <kostikbel@gmail.com>
Cc: Jaakko Heinonen <jh@freebsd.org>, 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: Tue, 2 Nov 2010 21:22:08 -0400

 --Sig_/7Pf4aeGVwmRcU.vpefS=CWm
 Content-Type: text/plain; charset=US-ASCII
 Content-Transfer-Encoding: quoted-printable
 
 On Tue, 2 Nov 2010 22:13:06 +0200
 Kostik Belousov <kostikbel@gmail.com> wrote:
 
 > >=20
 > > I have cc'd kan@ and kib@. Do you have ideas how to fix this
 > > correctly?
 >=20
 > Why do you think that your patch is not correct ?
 > I feel that more explicit handling of the state of the DAG is cleaner.
 <SKIP>
 
 This looks like a good fix.
 
 --=20
 Alexander Kabaev
 
 --Sig_/7Pf4aeGVwmRcU.vpefS=CWm
 Content-Type: application/pgp-signature; name=signature.asc
 Content-Disposition: attachment; filename=signature.asc
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.16 (FreeBSD)
 
 iD8DBQFM0LlEQ6z1jMm+XZYRAh/MAJ9BoGgzrCspsrSv0Eurra/jrKVcogCfbaTH
 ARgxgEeuAh+0Jr43zjqQtuc=
 =Lmr7
 -----END PGP SIGNATURE-----
 
 --Sig_/7Pf4aeGVwmRcU.vpefS=CWm--

From: "Arjan van Leeuwen" <freebsd-maintainer@opera.com>
To: "Kostik Belousov" <kostikbel@gmail.com>,
        "Alexander Kabaev"
 <kabaev@gmail.com>
Cc: "Jaakko Heinonen" <jh@freebsd.org>, bug-followup@freebsd.org,
        kan@freebsd.org
Subject: Re: misc/151861: dlclose() of library causes separately opened
 libraries to unload as well
Date: Wed, 03 Nov 2010 10:01:02 +0100

 On Wed, 03 Nov 2010 02:22:08 +0100, Alexander Kabaev <kabaev@gmail.com>  
 wrote:
 
 > On Tue, 2 Nov 2010 22:13:06 +0200
 > Kostik Belousov <kostikbel@gmail.com> wrote:
 >
 >> >
 >> > I have cc'd kan@ and kib@. Do you have ideas how to fix this
 >> > correctly?
 >>
 >> Why do you think that your patch is not correct ?
 >> I feel that more explicit handling of the state of the DAG is cleaner.
 > <SKIP>
 >
 > This looks like a good fix.
 
 I can confirm that this fix fixes both the test case and the far more  
 complicated crash in Opera. Thanks!
 
 Arjan
 
 -- 
 Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: misc/151861: commit references a PR
Date: Wed,  3 Nov 2010 09:23:17 +0000 (UTC)

 Author: kib
 Date: Wed Nov  3 09:23:08 2010
 New Revision: 214728
 URL: http://svn.freebsd.org/changeset/base/214728
 
 Log:
   If dlopen() is called for the dso that has been already loaded as a
   dependency, then the dso never has its DAG initialized. Empty DAG
   makes ref_dag() call in dlopen() a nop, and the dso refcount is off
   by one.
   
   Initialize the DAG on the first dlopen() call, using a boolean flag
   to prevent double initialization.
   
   From the PR (edited):
   Assume we have a library liba.so, containing a function a(), and a
   library libb.so, containing function b(). liba.so needs functionality
   from libb.so, so liba.so links in libb.so.
   
   An application doesn't know about the relation between these libraries,
   but needs to call a() and b(). It dlopen()s liba.so and obtains a
   pointer to a(), then it dlopen()s libb.so and obtains a pointer to b().
   
   As soon as the application doesn't need a() anymore, it dlclose()s liba.so.
   
   Expected result: the pointer to b() is still valid and can be called
   Actual result: the pointer to b() has become invalid, even though the
   application did not dlclose() the handle to libb.so. On calling b(), the
   application crashes with a segmentation fault.
   
   PR:	misc/151861
   Based on patch by:	jh
   Reviewed by:	kan
   Tested by:	Arjan van Leeuwen <freebsd-maintainer opera com>
   MFC after:	1 week
 
 Modified:
   head/libexec/rtld-elf/rtld.c
   head/libexec/rtld-elf/rtld.h
 
 Modified: head/libexec/rtld-elf/rtld.c
 ==============================================================================
 --- head/libexec/rtld-elf/rtld.c	Wed Nov  3 08:34:00 2010	(r214727)
 +++ head/libexec/rtld-elf/rtld.c	Wed Nov  3 09:23:08 2010	(r214728)
 @@ -1275,8 +1275,11 @@ init_dag(Obj_Entry *root)
  {
      DoneList donelist;
  
 +    if (root->dag_inited)
 +	    return;
      donelist_init(&donelist);
      init_dag1(root, root, &donelist);
 +    root->dag_inited = true;
  }
  
  static void
 @@ -2045,8 +2048,16 @@ dlopen(const char *name, int mode)
  	    }
  	} else {
  
 -	    /* Bump the reference counts for objects on this DAG. */
 -	    ref_dag(obj);
 +	    /*
 +	     * Bump the reference counts for objects on this DAG.  If
 +	     * this is the first dlopen() call for the object that was
 +	     * already loaded as a dependency, initialize the dag
 +	     * starting at it.
 +	     */
 +	    if (obj->dl_refcount == 1)
 +		init_dag(obj);
 +	    else
 +		ref_dag(obj);
  
  	    if (ld_tracing)
  		goto trace;
 
 Modified: head/libexec/rtld-elf/rtld.h
 ==============================================================================
 --- head/libexec/rtld-elf/rtld.h	Wed Nov  3 08:34:00 2010	(r214727)
 +++ head/libexec/rtld-elf/rtld.h	Wed Nov  3 09:23:08 2010	(r214728)
 @@ -222,6 +222,7 @@ typedef struct Struct_Obj_Entry {
      bool ref_nodel : 1;		/* Refcount increased to prevent dlclose */
      bool init_scanned: 1;	/* Object is already on init list. */
      bool on_fini_list: 1;	/* Object is already on fini list. */
 +    bool dag_inited : 1;	/* Object has its DAG initialized. */
  
      struct link_map linkmap;	/* For GDB and dlinfo() */
      Objlist dldags;		/* Object belongs to these dlopened DAGs (%) */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: Jaakko Heinonen <jh@FreeBSD.org>
To: Kostik Belousov <kostikbel@gmail.com>
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:06:49 +0200

 On 2010-11-02, Kostik Belousov wrote:
 > Why do you think that your patch is not correct ?
 
 Well, I didn't say that I think it's incorrect. :)
 
 > I feel that more explicit handling of the state of the DAG is cleaner.
 
 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.
 
 (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.)
 
 > --- a/libexec/rtld-elf/rtld.c
 > +++ b/libexec/rtld-elf/rtld.c
 > @@ -1275,8 +1275,11 @@ init_dag(Obj_Entry *root)
 >  {
 >      DoneList donelist;
 >  
 > +    if (root->dag_inited)
 > +	    return;
 
 Why init_dag() should be allowed to be called multiple times for an
 object?
 
 Thanks.
 -- 
 Jaakko

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

From: Jaakko Heinonen <jh@FreeBSD.org>
To: Kostik Belousov <kostikbel@gmail.com>
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 17:02:24 +0200

 On 2010-11-03, Kostik Belousov wrote:
 > > 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.
 
 If the object gets unloaded after dlclose(), this will not happen? I am
 not sure if I like that it can be called multiple times.
 
 > --- a/libexec/rtld-elf/rtld.c
 > +++ b/libexec/rtld-elf/rtld.c
 > @@ -1275,11 +1275,12 @@ init_dag(Obj_Entry *root)
 >  {
 >      DoneList donelist;
 >  
 > -    if (root->dag_inited)
 > -	    return;
 > -    donelist_init(&donelist);
 > -    init_dag1(root, root, &donelist);
 > -    root->dag_inited = true;
 > +    if (!root->dag_inited) {
 > +	donelist_init(&donelist);
 > +	init_dag1(root, root, &donelist);
 > +	root->dag_inited = true;
 > +    }
 > +    ref_dag(root);
 >  }
 
 If you are going to take this approach, why not remove init_dag() altogether
 and make ref_dag() to initialize the dag when necessary?
 
 Thanks for working on this.
 -- 
 Jaakko

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 17:14:08 +0200

 --MqBZZc8f0rLWAE1Q
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Wed, Nov 03, 2010 at 05:02:24PM +0200, Jaakko Heinonen wrote:
 > On 2010-11-03, Kostik Belousov wrote:
 > > > Why init_dag() should be allowed to be called multiple times for an
 > > > object?
 > >=20
 > > If already loaded object is dlopened, dlclosed, and then again dlopened,
 > > init_dag() will be called twice, one time for each dlopen.
 >=20
 > If the object gets unloaded after dlclose(), this will not happen? I am
 > not sure if I like that it can be called multiple times.
 Yes, for the case when dlclose() removes the last reference, the object
 is unloaded. But, if the object was loaded as dependency that is still
 valid, it will not.
 
 Assume that main executable is linked against b.so, and then
 dlopen("b.so");
 dlclose("b.so");
 dlopen("b.so");
 is called.
 
 >=20
 > > --- 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
 > If you are going to take this approach, why not remove init_dag() altoget=
 her
 > and make ref_dag() to initialize the dag when necessary?
 I like the explicit notion that ref_dag() does not initialize the DAG.
 We may add some assertion about state of the DAG there.
 
 I tried reverse change, always using init_dag(), there is only one
 place after the patch where ref_dag() is called, but init_dag() is not.
 The reason why I decided to call both is the same.
 
 --MqBZZc8f0rLWAE1Q
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (FreeBSD)
 
 iEYEARECAAYFAkzRfD8ACgkQC3+MBN1Mb4gbBgCdEp5jauPSC6s1bxijJABcTqdw
 Z/gAoI0cA6Xe5pL2K6NCXW82mMzAzSSI
 =xwJx
 -----END PGP SIGNATURE-----
 
 --MqBZZc8f0rLWAE1Q--

From: Jaakko Heinonen <jh@FreeBSD.org>
To: Kostik Belousov <kostikbel@gmail.com>
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 18:12:05 +0200

 On 2010-11-03, Kostik Belousov wrote:
 > > If you are going to take this approach, why not remove init_dag() altogether
 > > and make ref_dag() to initialize the dag when necessary?
 > I like the explicit notion that ref_dag() does not initialize the DAG.
 > We may add some assertion about state of the DAG there.
 
 OK. I don't like that init_dag() is used to increase reference count for
 already initialized DAGs but feel free to do whatever you think is
 best.
 
 -- 
 Jaakko

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 18:20:30 +0200

 --dPNPvpIcGJA2vEEo
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Wed, Nov 03, 2010 at 06:12:05PM +0200, Jaakko Heinonen wrote:
 > On 2010-11-03, Kostik Belousov wrote:
 > > > If you are going to take this approach, why not remove init_dag() alt=
 ogether
 > > > and make ref_dag() to initialize the dag when necessary?
 > > I like the explicit notion that ref_dag() does not initialize the DAG.
 > > We may add some assertion about state of the DAG there.
 >=20
 > OK. I don't like that init_dag() is used to increase reference count for
 > already initialized DAGs but feel free to do whatever you think is
 > best.
 I do not like it too, but this is the current interface of init_dag().
 Intermediate version of the latest patch removed the ref_dag() part
 from init_dag(). Would you prefer this ?
 
 --dPNPvpIcGJA2vEEo
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (FreeBSD)
 
 iEYEARECAAYFAkzRi84ACgkQC3+MBN1Mb4hTZQCg4gA9uxOWYQ1Znwk2dqIWXHXf
 UIwAn1fpTWW+N0nz7mawenn4o400FXCw
 =Hi4N
 -----END PGP SIGNATURE-----
 
 --dPNPvpIcGJA2vEEo--

From: Alexander Kabaev <kabaev@gmail.com>
To: Kostik Belousov <kostikbel@gmail.com>
Cc: Jaakko Heinonen <jh@freebsd.org>, 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:27:33 -0400

 --Sig_/MAre2Tk=MK8wez6egE69T8v
 Content-Type: text/plain; charset=US-ASCII
 Content-Transfer-Encoding: quoted-printable
 
 On Wed, 3 Nov 2010 18:20:30 +0200
 Kostik Belousov <kostikbel@gmail.com> wrote:
 ...
 > ready initialized DAGs but feel free to do whatever you think is
 > > best. =20
 > I do not like it too, but this is the current interface of init_dag().
 > Intermediate version of the latest patch removed the ref_dag() part
 > from init_dag(). Would you prefer this ?
 
 I would, but I lack time following all the patch versions flying
 around, so I am not sure I am talking about the right one.
 
 --=20
 Alexander Kabaev
 
 --Sig_/MAre2Tk=MK8wez6egE69T8v
 Content-Type: application/pgp-signature; name=signature.asc
 Content-Disposition: attachment; filename=signature.asc
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.16 (FreeBSD)
 
 iD8DBQFM0Y14Q6z1jMm+XZYRAhHEAKDjwf2kuwfLeCXGnw7CRuOg8W+mRQCfZ38F
 IRjAbnkaZxnaEmEoPcBmmNc=
 =HlRg
 -----END PGP SIGNATURE-----
 
 --Sig_/MAre2Tk=MK8wez6egE69T8v--

From: Kostik Belousov <kostikbel@gmail.com>
To: Alexander Kabaev <kabaev@gmail.com>
Cc: Jaakko Heinonen <jh@freebsd.org>,
        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 18:37:56 +0200

 --WrZzWSSrfsHeDS1u
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Wed, Nov 03, 2010 at 12:27:33PM -0400, Alexander Kabaev wrote:
 > On Wed, 3 Nov 2010 18:20:30 +0200
 > Kostik Belousov <kostikbel@gmail.com> wrote:
 > ...
 > > ready initialized DAGs but feel free to do whatever you think is
 > > > best. =20
 > > I do not like it too, but this is the current interface of init_dag().
 > > Intermediate version of the latest patch removed the ref_dag() part
 > > from init_dag(). Would you prefer this ?
 >=20
 > I would, but I lack time following all the patch versions flying
 > around, so I am not sure I am talking about the right one.
 
 By intermediate I mean private intermediate state in my working tree.
 Below is the patch augmented with the change to not call ref_dag()
 from init_dag().
 
 diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
 index f1ffc3e..b5fb6e1 100644
 --- a/libexec/rtld-elf/rtld.c
 +++ b/libexec/rtld-elf/rtld.c
 @@ -1276,7 +1276,7 @@ init_dag(Obj_Entry *root)
      DoneList donelist;
 =20
      if (root->dag_inited)
 -	    return;
 +	return;
      donelist_init(&donelist);
      init_dag1(root, root, &donelist);
      root->dag_inited =3D true;
 @@ -1290,7 +1290,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)
 @@ -2031,6 +2030,7 @@ dlopen(const char *name, int mode)
  	    assert(*old_obj_tail =3D=3D obj);
  	    result =3D load_needed_objects(obj, RTLD_LO_DLOPEN);
  	    init_dag(obj);
 +	    ref_dag(obj);
  	    if (result !=3D -1)
  		result =3D rtld_verify_versions(&obj->dagmembers);
  	    if (result !=3D -1 && ld_tracing)
 @@ -2054,10 +2054,8 @@ 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);
 +	    ref_dag(obj);
 =20
  	    if (ld_tracing)
  		goto trace;
 
 --WrZzWSSrfsHeDS1u
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (FreeBSD)
 
 iEYEARECAAYFAkzRj+MACgkQC3+MBN1Mb4hlhgCePxx85hsAX8dFQNcd0YQPOUix
 ae8AoK/CdgarYRhNpgRnkuFh2t0Tq3rV
 =eA3x
 -----END PGP SIGNATURE-----
 
 --WrZzWSSrfsHeDS1u--

From: Jaakko Heinonen <jh@FreeBSD.org>
To: Kostik Belousov <kostikbel@gmail.com>
Cc: Alexander Kabaev <kabaev@gmail.com>,
	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 20:48:24 +0200

 On 2010-11-03, Kostik Belousov wrote:
 > By intermediate I mean private intermediate state in my working tree.
 > Below is the patch augmented with the change to not call ref_dag()
 > from init_dag().
 
 I prefer this one. Could you also add assert(root->dag_inited); to
 ref_dag() and unref_dag()?
 
 -- 
 Jaakko

From: Kostik Belousov <kostikbel@gmail.com>
To: Jaakko Heinonen <jh@freebsd.org>
Cc: Alexander Kabaev <kabaev@gmail.com>,
        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 22:27:50 +0200

 --45BN1MGjfyYG1snq
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 On Wed, Nov 03, 2010 at 08:48:24PM +0200, Jaakko Heinonen wrote:
 > On 2010-11-03, Kostik Belousov wrote:
 > > By intermediate I mean private intermediate state in my working tree.
 > > Below is the patch augmented with the change to not call ref_dag()
 > > from init_dag().
 >=20
 > I prefer this one. Could you also add assert(root->dag_inited); to
 > ref_dag() and unref_dag()?
 
 This is reasonable but IMHO risky asserts.
 I added them as requested, will see how it going.
 
 Any further suggestions or objections ? If not, I will commit this tomorrow
 morning.
 
 diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
 index f1ffc3e..bf21586 100644
 --- a/libexec/rtld-elf/rtld.c
 +++ b/libexec/rtld-elf/rtld.c
 @@ -1276,7 +1276,7 @@ init_dag(Obj_Entry *root)
      DoneList donelist;
 =20
      if (root->dag_inited)
 -	    return;
 +	return;
      donelist_init(&donelist);
      init_dag1(root, root, &donelist);
      root->dag_inited =3D true;
 @@ -1290,7 +1290,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)
 @@ -2031,6 +2030,7 @@ dlopen(const char *name, int mode)
  	    assert(*old_obj_tail =3D=3D obj);
  	    result =3D load_needed_objects(obj, RTLD_LO_DLOPEN);
  	    init_dag(obj);
 +	    ref_dag(obj);
  	    if (result !=3D -1)
  		result =3D rtld_verify_versions(&obj->dagmembers);
  	    if (result !=3D -1 && ld_tracing)
 @@ -2054,10 +2054,8 @@ 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);
 +	    ref_dag(obj);
 =20
  	    if (ld_tracing)
  		goto trace;
 @@ -3085,6 +3083,7 @@ ref_dag(Obj_Entry *root)
  {
      Objlist_Entry *elm;
 =20
 +    assert(root->dag_inited);
      STAILQ_FOREACH(elm, &root->dagmembers, link)
  	elm->obj->refcount++;
  }
 @@ -3094,6 +3093,7 @@ unref_dag(Obj_Entry *root)
  {
      Objlist_Entry *elm;
 =20
 +    assert(root->dag_inited);
      STAILQ_FOREACH(elm, &root->dagmembers, link)
  	elm->obj->refcount--;
  }
 
 --45BN1MGjfyYG1snq
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (FreeBSD)
 
 iEYEARECAAYFAkzRxcYACgkQC3+MBN1Mb4i2OwCfZBkstpjnLsrNvOrdin/1W2C/
 UDoAnAjHo3/SWSm7ZC46+Vvoa7ZGI33J
 =EVSb
 -----END PGP SIGNATURE-----
 
 --45BN1MGjfyYG1snq--

From: Alexander Kabaev <kabaev@gmail.com>
To: Kostik Belousov <kostikbel@gmail.com>
Cc: Jaakko Heinonen <jh@freebsd.org>, 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 17:55:42 -0400

 --Sig_/ykcQFMB+TmLB+hf/2HXyXRY
 Content-Type: text/plain; charset=US-ASCII
 Content-Transfer-Encoding: quoted-printable
 
 On Wed, 3 Nov 2010 18:37:56 +0200
 Kostik Belousov <kostikbel@gmail.com> wrote:
 
 > On Wed, Nov 03, 2010 at 12:27:33PM -0400, Alexander Kabaev wrote:
 > > On Wed, 3 Nov 2010 18:20:30 +0200
 > > Kostik Belousov <kostikbel@gmail.com> wrote:
 > > ...
 > > > ready initialized DAGs but feel free to do whatever you think is
 > > > > best. =20
 > > > I do not like it too, but this is the current interface of
 > > > init_dag(). Intermediate version of the latest patch removed the
 > > > ref_dag() part from init_dag(). Would you prefer this ?
 > >=20
 > > I would, but I lack time following all the patch versions flying
 > > around, so I am not sure I am talking about the right one.
 >=20
 > By intermediate I mean private intermediate state in my working tree.
 > Below is the patch augmented with the change to not call ref_dag()
 > from init_dag().
 >=20
 > diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
 > index f1ffc3e..b5fb6e1 100644
 > --- a/libexec/rtld-elf/rtld.c
 > +++ b/libexec/rtld-elf/rtld.c
 > @@ -1276,7 +1276,7 @@ init_dag(Obj_Entry *root)
 >      DoneList donelist;
 > =20
 >      if (root->dag_inited)
 > -	    return;
 > +	return;
 >      donelist_init(&donelist);
 >      init_dag1(root, root, &donelist);
 >      root->dag_inited =3D true;
 > @@ -1290,7 +1290,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->next) @@ -2031,6 +2030,7 @@ dlopen(const char *name, int mode)
 >  	    assert(*old_obj_tail =3D=3D obj);
 >  	    result =3D load_needed_objects(obj, RTLD_LO_DLOPEN);
 >  	    init_dag(obj);
 > +	    ref_dag(obj);
 >  	    if (result !=3D -1)
 >  		result =3D rtld_verify_versions(&obj->dagmembers);
 >  	    if (result !=3D -1 && ld_tracing)
 > @@ -2054,10 +2054,8 @@ 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);
 > +	    ref_dag(obj);
 > =20
 >  	    if (ld_tracing)
 >  		goto trace;
 
 This is one that is least confusing and I like it. Thanks.=20
 
 --=20
 Alexander Kabaev
 
 --Sig_/ykcQFMB+TmLB+hf/2HXyXRY
 Content-Type: application/pgp-signature; name=signature.asc
 Content-Disposition: attachment; filename=signature.asc
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.16 (FreeBSD)
 
 iD8DBQFM0dpnQ6z1jMm+XZYRAn1DAKC2AOFZjncDv3aIwYHdciHTN28nOACg5d/X
 YZmVyabqGdtJC3+czb+KZUo=
 =FiaC
 -----END PGP SIGNATURE-----
 
 --Sig_/ykcQFMB+TmLB+hf/2HXyXRY--
State-Changed-From-To: open->patched 
State-Changed-By: jh 
State-Changed-When: Thu Nov 11 16:42:23 UTC 2010 
State-Changed-Why:  
Fixed in head and stable/8 (revisions 214728, 214777 and 215084). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=151861 
State-Changed-From-To: patched->closed 
State-Changed-By: remko 
State-Changed-When: Wed Oct 12 14:46:10 UTC 2011 
State-Changed-Why:  
Fixed in HEAD and 8-stable, seems that there is no more MFC'ing, closing 
the ticket. someone [tm] should reopen this if there is need for 
additional MFC 

http://www.freebsd.org/cgi/query-pr.cgi?pr=151861 
>Unformatted:
