patch for threads/76690 - critical - fork hang in child for -lc_r

Andriy Tkachuk andrit at ukr.net
Wed Mar 2 14:56:24 GMT 2005


Hi folks.

I spent some time on the problem in $subj and found some
solution that seems to be working but i'm not sure about it's
architectural correctness because libc was changed little bit ;)

here it is:

# diff -u -r lib lib.patched
diff -u -r lib/libc/stdlib/malloc.c lib.patched/libc/stdlib/malloc.c
--- lib/libc/stdlib/malloc.c    Sun Feb 27 22:46:16 2005
+++ lib.patched/libc/stdlib/malloc.c    Wed Mar  2 19:55:24 2005
@@ -74,7 +74,7 @@
      */
 #   include "libc_private.h"
 #   include "spinlock.h"
-    static spinlock_t thread_lock      = _SPINLOCK_INITIALIZER;
+    spinlock_t thread_lock     = _SPINLOCK_INITIALIZER;
     spinlock_t *__malloc_lock          = &thread_lock;
 #   define _MALLOC_LOCK()              if (__isthreaded) _SPINLOCK(&thread_lock);
 #   define _MALLOC_UNLOCK()            if (__isthreaded) _SPINUNLOCK(&thread_lock);
diff -u -r lib/libc_r/uthread/uthread_fork.c lib.patched/libc_r/uthread/uthread_fork.c
--- lib/libc_r/uthread/uthread_fork.c   Fri Dec 10 09:06:45 2004
+++ lib.patched/libc_r/uthread/uthread_fork.c   Wed Mar  2 20:10:49 2005
@@ -61,6 +61,8 @@
        _thread_kern_sig_defer();

        _pthread_mutex_lock(&_atfork_mutex);
+       extern spinlock_t thread_lock;
+       _SPINLOCK(&thread_lock);

        /* Run down atfork prepare handlers. */
        TAILQ_FOREACH_REVERSE(af, &_atfork_list, atfork_head, qe) {
@@ -70,6 +72,8 @@

        /* Fork a new process: */
        if ((ret = __sys_fork()) != 0) {
+               _SPINUNLOCK(&thread_lock);
+
                /* Run down atfork parent handlers. */
                TAILQ_FOREACH(af, &_atfork_list, qe) {
                        if (af->parent != NULL)
@@ -78,6 +82,8 @@
                _pthread_mutex_unlock(&_atfork_mutex);

        } else {
+               _SPINUNLOCK(&thread_lock);
+
                /* Close the pthread kernel pipe: */
                __sys_close(_thread_kern_pipe[0]);
                __sys_close(_thread_kern_pipe[1]);


The main problem with it is that after fork child inherits
from the parent inconsist heap. So the obvious solution is
to synchronyze the fork and heap manipulations. I didn't find
the easyest way how to get the lock variable from malloc lib
as to open this variable deleting static spec.

So what do you think guys about this patch?

Thanks,
  Andriy Tkachuk.






More information about the freebsd-threads mailing list