tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

fork() and ld.elf_so



Hi all,
attached patch introduces the necessary hooks around fork() to prevent
lock starvation in multi-thread programs. Basic issue:
Thread 1 calls dlopen()
Thread 2 calls fork()
Child tries to bind a weak symbol
-> Bomb

Joerg
Index: include/dlfcn.h
===================================================================
RCS file: /home/joerg/repo/netbsd/src/include/dlfcn.h,v
retrieving revision 1.22
diff -u -p -r1.22 dlfcn.h
--- include/dlfcn.h     24 Dec 2010 12:41:42 -0000      1.22
+++ include/dlfcn.h     28 Mar 2011 18:59:57 -0000
@@ -110,4 +110,15 @@ __END_DECLS
 #endif
 #endif /* _NETBSD_SOURCE */
 
+#if defined(_LIBC) || defined(_RTLD_SOURCE)
+#define        RTLD_LOCK_PRE_FORK              1
+#define        RTLD_LOCK_POST_FORK             2
+#endif
+
+#if defined(_LIBC)
+__weakref_visible void _rtld_lock_handler(int) __weak_reference(_rtld_lock);
+#elif defined(_RTLD_SOURCE)
+__dso_public void _rtld_lock(int);
+#endif
+
 #endif /* !defined(_DLFCN_H_) */
Index: lib/libc/gen/pthread_atfork.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/lib/libc/gen/pthread_atfork.c,v
retrieving revision 1.8
diff -u -p -r1.8 pthread_atfork.c
--- lib/libc/gen/pthread_atfork.c       28 Apr 2008 20:22:59 -0000      1.8
+++ lib/libc/gen/pthread_atfork.c       28 Mar 2011 18:56:29 -0000
@@ -36,6 +36,7 @@ __RCSID("$NetBSD: pthread_atfork.c,v 1.8
 
 #include "namespace.h"
 
+#include <dlfcn.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -155,7 +156,11 @@ fork(void)
        SIMPLEQ_FOREACH(iter, &prepareq, next)
                (*iter->fn)();
 
+       if (_rtld_lock_handler)
+               (*_rtld_lock_handler)(RTLD_LOCK_PRE_FORK);
        ret = __fork();
+       if (_rtld_lock_handler)
+               (*_rtld_lock_handler)(RTLD_LOCK_POST_FORK);
 
        if (ret != 0) {
                /*
Index: libexec/ld.elf_so/rtld.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/libexec/ld.elf_so/rtld.c,v
retrieving revision 1.147
diff -u -p -r1.147 rtld.c
--- libexec/ld.elf_so/rtld.c    28 Mar 2011 00:37:40 -0000      1.147
+++ libexec/ld.elf_so/rtld.c    28 Mar 2011 18:50:15 -0000
@@ -1397,6 +1397,24 @@ _rtld_objlist_remove(Objlist *list, Obj_
        }
 }
 
+void
+_rtld_lock(int arg)
+{
+       switch (arg) {
+       default:
+               dbg(("%s: invalid argument: %d", __func__, arg));
+               break;
+       case RTLD_LOCK_PRE_FORK:
+               _rtld_exclusive_enter();
+               _rtld_mutex_may_recurse = true;
+               break;
+       case RTLD_LOCK_POST_FORK:
+               _rtld_mutex_may_recurse = false;
+               _rtld_exclusive_exit();
+               break;
+       }
+}
+
 #define        RTLD_EXCLUSIVE_MASK     0x80000000U
 static volatile unsigned int _rtld_mutex;
 static volatile unsigned int _rtld_waiter_exclusive;
Index: libexec/ld.elf_so/symbol.c
===================================================================
RCS file: /home/joerg/repo/netbsd/src/libexec/ld.elf_so/symbol.c,v
retrieving revision 1.56
diff -u -p -r1.56 symbol.c
--- libexec/ld.elf_so/symbol.c  12 Mar 2011 22:54:36 -0000      1.56
+++ libexec/ld.elf_so/symbol.c  28 Mar 2011 18:50:47 -0000
@@ -93,6 +93,7 @@ _rtld_is_exported(const Elf_Sym *def)
                (fptr_t)dladdr,
                (fptr_t)dlinfo,
                (fptr_t)dl_iterate_phdr,
+               (fptr_t)_rtld_lock,
 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
                (fptr_t)_rtld_tls_allocate,
                (fptr_t)_rtld_tls_free,


Home | Main Index | Thread Index | Old Index