dlopen() and dlclose() are not MT-safe?

Kostik Belousov kostikbel at gmail.com
Wed Mar 22 17:43:23 UTC 2006


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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20060322/26f50d11/attachment.pgp


More information about the freebsd-hackers mailing list