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. */
pgpD9n9hHcqBX.pgp
Description: PGP signature