diff --git a/libc/intrin/pthreadlock.c b/libc/intrin/pthreadlock.c index 68d55325a..3fd1d564a 100644 --- a/libc/intrin/pthreadlock.c +++ b/libc/intrin/pthreadlock.c @@ -20,6 +20,10 @@ pthread_spinlock_t _pthread_lock_obj; +void _pthread_init(void) { + (void)pthread_spin_init(&_pthread_lock_obj, 0); +} + void _pthread_lock(void) { pthread_spin_lock(&_pthread_lock_obj); } diff --git a/libc/proc/fork.c b/libc/proc/fork.c index aa437dc6d..68f020fe1 100644 --- a/libc/proc/fork.c +++ b/libc/proc/fork.c @@ -46,6 +46,7 @@ static void _onfork_prepare(void) { if (_weaken(_pthread_onfork_prepare)) { _weaken(_pthread_onfork_prepare)(); } + _pthread_lock(); __fds_lock(); __mmi_lock(); } @@ -53,11 +54,26 @@ static void _onfork_prepare(void) { static void _onfork_parent(void) { __mmi_unlock(); __fds_unlock(); + _pthread_unlock(); if (_weaken(_pthread_onfork_parent)) { _weaken(_pthread_onfork_parent)(); } } +static void _onfork_child(void) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + extern pthread_mutex_t __mmi_lock_obj; + pthread_mutex_init(&__mmi_lock_obj, &attr); + pthread_mutex_init(&__fds_lock_obj, &attr); + pthread_mutexattr_destroy(&attr); + _pthread_init(); + if (_weaken(_pthread_onfork_child)) { + _weaken(_pthread_onfork_child)(); + } +} + int _fork(uint32_t dwCreationFlags) { struct Dll *e; int ax, dx, tid, parent; @@ -117,8 +133,8 @@ int _fork(uint32_t dwCreationFlags) { atomic_store_explicit(&pt->pt_canceled, false, memory_order_relaxed); // run user fork callbacks - if (__threaded && _weaken(_pthread_onfork_child)) { - _weaken(_pthread_onfork_child)(); + if (__threaded) { + _onfork_child(); } STRACE("fork() → 0 (child of %d)", parent); } else { diff --git a/libc/thread/posixthread.internal.h b/libc/thread/posixthread.internal.h index cacd9e344..b0d56e94c 100644 --- a/libc/thread/posixthread.internal.h +++ b/libc/thread/posixthread.internal.h @@ -105,6 +105,7 @@ intptr_t _pthread_syshand(struct PosixThread *) libcesque; long _pthread_cancel_ack(void) libcesque; void _pthread_decimate(void) libcesque; void _pthread_free(struct PosixThread *, bool) libcesque; +void _pthread_init(void) libcesque; void _pthread_lock(void) libcesque; void _pthread_onfork_child(void) libcesque; void _pthread_onfork_parent(void) libcesque; diff --git a/libc/thread/pthread_atfork.c b/libc/thread/pthread_atfork.c index c20ec1859..fd5cfa34a 100644 --- a/libc/thread/pthread_atfork.c +++ b/libc/thread/pthread_atfork.c @@ -46,8 +46,6 @@ static struct AtForks { atomic_int allocated; } _atforks; -extern pthread_spinlock_t _pthread_lock_obj; - static void _pthread_onfork(int i) { struct AtFork *a; unassert(0 <= i && i <= 2); @@ -64,23 +62,13 @@ static void _pthread_onfork(int i) { void _pthread_onfork_prepare(void) { _pthread_onfork(0); - _pthread_lock(); } void _pthread_onfork_parent(void) { - _pthread_unlock(); _pthread_onfork(1); } void _pthread_onfork_child(void) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - extern pthread_mutex_t __mmi_lock_obj; - pthread_mutex_init(&__mmi_lock_obj, &attr); - pthread_mutex_init(&__fds_lock_obj, &attr); - pthread_mutexattr_destroy(&attr); - (void)pthread_spin_init(&_pthread_lock_obj, 0); _pthread_onfork(2); }