diff options
author | Khem Raj <kraj@mvista.com> | 2008-10-11 08:52:58 +0000 |
---|---|---|
committer | Khem Raj <kraj@mvista.com> | 2008-10-11 08:52:58 +0000 |
commit | 6494060312de389feb65ad32bb411fcc64e821b7 (patch) | |
tree | b2c735bba6b667b8cf056a858dc216c14590c138 /libpthread/linuxthreads.old/ptfork.c | |
parent | 47b2dbaaac9757496eb9d419e1912250354d30d1 (diff) |
Fix bug 4994 hangs on read(). I have tested the patch extensibly on ARM/LT.old.
Thank you Chase Douglas for reporting it and for the patch.
Diffstat (limited to 'libpthread/linuxthreads.old/ptfork.c')
-rw-r--r-- | libpthread/linuxthreads.old/ptfork.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/libpthread/linuxthreads.old/ptfork.c b/libpthread/linuxthreads.old/ptfork.c index c34ea8104..7a5749efc 100644 --- a/libpthread/linuxthreads.old/ptfork.c +++ b/libpthread/linuxthreads.old/ptfork.c @@ -20,6 +20,7 @@ #ifdef __ARCH_USE_MMU__ +#include <bits/uClibc_mutex.h> #include <stddef.h> #include <stdlib.h> #include <unistd.h> @@ -36,6 +37,16 @@ static struct handler_list * pthread_atfork_prepare = NULL; static struct handler_list * pthread_atfork_parent = NULL; static struct handler_list * pthread_atfork_child = NULL; +#ifdef __MALLOC__ +__UCLIBC_MUTEX_EXTERN(__malloc_heap_lock); +__UCLIBC_MUTEX_EXTERN(__malloc_sbrk_lock); +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ +__UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock); +#endif +#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) +__UCLIBC_MUTEX_EXTERN(__malloc_lock); +#endif + static void pthread_insert_list(struct handler_list ** list, void (*handler)(void), struct handler_list * newlist, @@ -78,6 +89,10 @@ static __inline__ void pthread_call_handlers(struct handler_list * list) for (/*nothing*/; list != NULL; list = list->next) (list->handler)(); } +void __pthread_once_fork_prepare(void); +void __pthread_once_fork_child(void); +void __pthread_once_fork_parent(void); + extern __typeof(fork) __libc_fork; pid_t __fork(void) attribute_hidden; @@ -90,14 +105,47 @@ pid_t __fork(void) prepare = pthread_atfork_prepare; child = pthread_atfork_child; parent = pthread_atfork_parent; - __pthread_mutex_unlock(&pthread_atfork_lock); pthread_call_handlers(prepare); + + __pthread_once_fork_prepare(); +#ifdef __MALLOC__ + __pthread_mutex_lock(&__malloc_sbrk_lock); + __pthread_mutex_lock(&__malloc_heap_lock); +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __pthread_mutex_lock(&__malloc_mmb_heap_lock); +#endif +#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __pthread_mutex_lock(&__malloc_lock); +#endif + pid = __libc_fork(); if (pid == 0) { +#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __libc_lock_init_recursive(__malloc_lock); +#elif defined(__MALLOC__) +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __libc_lock_init_adaptive(__malloc_mmb_heap_lock); +#endif + __libc_lock_init_adaptive(__malloc_heap_lock); + __libc_lock_init(__malloc_sbrk_lock); +#endif + __libc_lock_init_adaptive(pthread_atfork_lock); __pthread_reset_main_thread(); __fresetlockfiles(); + __pthread_once_fork_child(); pthread_call_handlers(child); } else { +#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __pthread_mutex_unlock(&__malloc_lock); +#elif defined(__MALLOC__) +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __pthread_mutex_unlock(&__malloc_mmb_heap_lock); +#endif + __pthread_mutex_unlock(&__malloc_heap_lock); + __pthread_mutex_unlock(&__malloc_sbrk_lock); +#endif + __pthread_mutex_unlock(&pthread_atfork_lock); + __pthread_once_fork_parent(); pthread_call_handlers(parent); } return pid; |