diff options
author | deischen <deischen@FreeBSD.org> | 2003-11-04 20:04:45 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2003-11-04 20:04:45 +0000 |
commit | 1191fa7e324052c4d97e45f85cbb566eb985c1c6 (patch) | |
tree | c66d125bd34129e0d434c2444369c5dd31c55ad0 /lib/libkse/thread/thr_fork.c | |
parent | 573b8090444db7cfee8d60b937cc6d39632c8bbc (diff) | |
download | FreeBSD-src-1191fa7e324052c4d97e45f85cbb566eb985c1c6.zip FreeBSD-src-1191fa7e324052c4d97e45f85cbb566eb985c1c6.tar.gz |
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
Diffstat (limited to 'lib/libkse/thread/thr_fork.c')
-rw-r--r-- | lib/libkse/thread/thr_fork.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/lib/libkse/thread/thr_fork.c b/lib/libkse/thread/thr_fork.c index f640614..6989174 100644 --- a/lib/libkse/thread/thr_fork.c +++ b/lib/libkse/thread/thr_fork.c @@ -37,9 +37,13 @@ #include <unistd.h> #include <fcntl.h> #include <pthread.h> +#include <spinlock.h> #include <sys/signalvar.h> #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); |