From 1191fa7e324052c4d97e45f85cbb566eb985c1c6 Mon Sep 17 00:00:00 2001 From: deischen Date: Tue, 4 Nov 2003 20:04:45 +0000 Subject: Add an implementation for pthread_atfork(). Aside from the POSIX requirements for pthread_atfork(), when fork()ing, take the malloc lock to keep malloc state consistent in the child. Reviewed by: davidxu --- lib/libpthread/thread/thr_fork.c | 43 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'lib/libpthread/thread/thr_fork.c') diff --git a/lib/libpthread/thread/thr_fork.c b/lib/libpthread/thread/thr_fork.c index f640614..6989174 100644 --- a/lib/libpthread/thread/thr_fork.c +++ b/lib/libpthread/thread/thr_fork.c @@ -37,9 +37,13 @@ #include #include #include +#include #include #include "thr_private.h" +extern spinlock_t *__malloc_lock; +#pragma weak __malloc_lock + __weak_reference(_fork, fork); pid_t @@ -47,6 +51,7 @@ _fork(void) { sigset_t sigset, oldset; struct pthread *curthread; + struct pthread_atfork *af; pid_t ret; int errsave; @@ -66,18 +71,48 @@ _fork(void) SIGFILLSET(sigset); __sys_sigprocmask(SIG_SETMASK, &sigset, &oldset); } + + _pthread_mutex_lock(&_thr_atfork_mutex); + + /* Run down atfork prepare handlers. */ + TAILQ_FOREACH_REVERSE(af, &_thr_atfork_list, atfork_head, qe) { + if (af->prepare != NULL) + af->prepare(); + } + /* Fork a new process: */ + if ((_kse_isthreaded() != 0) && (__malloc_lock != NULL)) { + _spinlock(__malloc_lock); + } if ((ret = __sys_fork()) == 0) { /* Child process */ - _kse_single_thread(curthread); + errsave = errno; + /* Kernel signal mask is restored in _kse_single_thread */ + _kse_single_thread(curthread); + + /* Run down atfork child handlers. */ + TAILQ_FOREACH(af, &_thr_atfork_list, qe) { + if (af->child != NULL) + af->child(); + } + _thr_mutex_reinit(&_thr_atfork_mutex); } else { + if ((_kse_isthreaded() != 0) && (__malloc_lock != NULL)) { + _spinunlock(__malloc_lock); + } + errsave = errno; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { - errsave = errno; __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); - errno = errsave; - } + } + /* Run down atfork parent handlers. */ + TAILQ_FOREACH(af, &_thr_atfork_list, qe) { + if (af->parent != NULL) + af->parent(); + } + _pthread_mutex_unlock(&_thr_atfork_mutex); } + errno = errsave; /* Return the process ID: */ return (ret); -- cgit v1.1