On Wed, Mar 22, 2006 at 07:43:12PM +0200, Kostik Belousov wrote:
> On Wed, Mar 22, 2006 at 11:32:09PM +0900, Kazuaki Oda wrote:
> > Hello,
> > 
> > I compiled the following code on 6.1-PRERELEASE and ran:
> > 
> > dltest.c
> > ----------------------------------------------------------------------
> > #include <err.h>
> > #include <dlfcn.h>
> > #include <pthread.h>
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <unistd.h>
> > 
> > #define NTHREADS    10
> > 
> > void *func(void *dummy);
> > 
> > int main(void)
> > {
> >     pthread_t tids[NTHREADS];
> >     int error;
> >     int i;
> > 
> >     for (i = 0; i < NTHREADS; i++) {
> >     error = pthread_create(&tids[i], NULL, func, NULL);
> >     if (error)
> >         errc(1, error, "pthread_create");
> >     }
> > 
> >     for (;;)
> >     sleep(1);
> > 
> >     /* NOTREACHED */
> > 
> >     exit(0);
> > }
> > 
> > void *func(void *dummy)
> > {
> >     void *h;
> > 
> >     for (;;) {
> >     if ((h = dlopen("/usr/lib/libm.so", RTLD_NOW)) == NULL)
> >         errx(1, "dlopen: %s", dlerror());
> >     if (dlclose(h) == -1)
> >         errx(1, "dlclose: %s", dlerror());
> >     }
> > 
> >     /* NOTREACHED */
> > 
> >     return (NULL);
> > }
> > ----------------------------------------------------------------------
> > 
> > % cc -Wall -o dltest dltest.c -lpthread
> > % ./dltest
> > ld-elf.so.1: assert failed: /usr/src/libexec/rtld-elf/rtld.c:2445
> > Segmentation fault (core dumped)
> > 
> > % cc -Wall -o dltest dltest.c -lthr
> > % ./dltest
> > % ld-elf.so.1: assert failed: /usr/src/libexec/rtld-elf/rtld.c:1723
> > Abort (core dumped)
> > 
> > Hmm, it seems dlopen() and dlclose() are not MT-safe.  Is this a known
> > issue?
> > 
> > --
> > Kazuaki Oda
> 
> The following patch put some relief for the problem:
> 
> Index: libexec/rtld-elf/rtld.c                                                
>   ===================================================================
> RCS file: /usr/local/arch/ncvs/src/libexec/rtld-elf/rtld.c,v
> retrieving revision 1.112
> diff -u -r1.112 rtld.c
> --- libexec/rtld-elf/rtld.c     24 Dec 2005 15:37:30 -0000      1.112
> +++ libexec/rtld-elf/rtld.c     22 Mar 2006 17:33:06 -0000
> @@ -1688,6 +1688,12 @@
>         wlock_release(rtld_bind_lock, lockstate);
>         objlist_call_fini(&list_fini);
>         lockstate = wlock_acquire(rtld_bind_lock);
> +       if (root->refcount == 0) {
> +               _rtld_error("%s: object busy", root->path);
> +               wlock_release(rtld_bind_lock, lockstate);
> +               return -1;
> +       }
> +
>         objlist_remove_unref(&list_fini);
> 
>         /* Finish cleaning up the newly-unreferenced objects. */
> 
> 
> But it still allows for the mess of _init/_fini simultaneous calls
> from different threads. SUSv3 does not mention constructors/destructors.

Oops. Completely reversed condition in the if. :(. Also, I don't think it
shall returns the error in this situation. New take:

Index: libexec/rtld-elf/rtld.c
===================================================================
RCS file: /usr/local/arch/ncvs/src/libexec/rtld-elf/rtld.c,v
retrieving revision 1.112
diff -u -r1.112 rtld.c
--- libexec/rtld-elf/rtld.c     24 Dec 2005 15:37:30 -0000      1.112
+++ libexec/rtld-elf/rtld.c     22 Mar 2006 19:03:12 -0000
@@ -1688,6 +1688,11 @@
        wlock_release(rtld_bind_lock, lockstate);
        objlist_call_fini(&list_fini);
        lockstate = wlock_acquire(rtld_bind_lock);
+       if (root->refcount != 0) {
+               wlock_release(rtld_bind_lock, lockstate);
+               return 0;
+       }
+
        objlist_remove_unref(&list_fini);

        /* Finish cleaning up the newly-unreferenced objects. */

Attachment: pgpD9n9hHcqBX.pgp
Description: PGP signature

Reply via email to