From 37a87b6214468a4caf40d3ed2601ff26aa70efa7 Mon Sep 17 00:00:00 2001 From: grog Date: Fri, 10 Dec 2004 03:36:45 +0000 Subject: Add pthread_atfork(). PR: bin/68841 Submitted by: Dan Nelson --- lib/libc_r/uthread/Makefile.inc | 1 + lib/libc_r/uthread/pthread_private.h | 10 +++++++ lib/libc_r/uthread/uthread_atfork.c | 56 ++++++++++++++++++++++++++++++++++++ lib/libc_r/uthread/uthread_fork.c | 24 +++++++++++++++- lib/libc_r/uthread/uthread_init.c | 2 ++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 lib/libc_r/uthread/uthread_atfork.c (limited to 'lib') diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc index 06c5a70..6d457c1 100644 --- a/lib/libc_r/uthread/Makefile.inc +++ b/lib/libc_r/uthread/Makefile.inc @@ -10,6 +10,7 @@ SRCS+= \ uthread_acl_set_fd.c \ uthread_acl_aclcheck_fd.c \ uthread_aio_suspend.c \ + uthread_atfork.c \ uthread_attr_destroy.c \ uthread_attr_init.c \ uthread_attr_getdetachstate.c \ diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index ecd330c..0d49da1 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -451,6 +451,13 @@ struct pthread_cleanup { void *routine_arg; }; +struct pthread_atfork { + TAILQ_ENTRY(pthread_atfork) qe; + void (*prepare)(void); + void (*parent)(void); + void (*child)(void); +}; + struct pthread_attr { int sched_policy; int sched_inherit; @@ -1025,6 +1032,9 @@ SCLASS struct pthread *_thread_initial ; #endif +SCLASS TAILQ_HEAD(atfork_head, pthread_atfork) _atfork_list; +SCLASS pthread_mutex_t _atfork_mutex; + /* Default thread attributes: */ SCLASS struct pthread_attr _pthread_attr_default #ifdef GLOBAL_PTHREAD_PRIVATE diff --git a/lib/libc_r/uthread/uthread_atfork.c b/lib/libc_r/uthread/uthread_atfork.c new file mode 100644 index 0000000..8a09468 --- /dev/null +++ b/lib/libc_r/uthread/uthread_atfork.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003 Daniel Eischen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include +#include +#include +#include "pthread_private.h" + +__weak_reference(_pthread_atfork, pthread_atfork); + +int +_pthread_atfork(void (*prepare)(void), void (*parent)(void), + void (*child)(void)) +{ + struct pthread_atfork *af; + + if (_thread_initial == NULL) + _thread_init(); + + if ((af = malloc(sizeof(struct pthread_atfork))) == NULL) + return (ENOMEM); + + af->prepare = prepare; + af->parent = parent; + af->child = child; + _pthread_mutex_lock(&_atfork_mutex); + TAILQ_INSERT_TAIL(&_atfork_list, af, qe); + _pthread_mutex_unlock(&_atfork_mutex); + return (0); +} + diff --git a/lib/libc_r/uthread/uthread_fork.c b/lib/libc_r/uthread/uthread_fork.c index dd6d3ff..0166a57 100644 --- a/lib/libc_r/uthread/uthread_fork.c +++ b/lib/libc_r/uthread/uthread_fork.c @@ -48,6 +48,7 @@ pid_t _fork(void) { struct pthread *curthread = _get_curthread(); + struct pthread_atfork *af; int i, flags, use_deadlist = 0; pid_t ret; pthread_t pthread; @@ -59,9 +60,23 @@ _fork(void) */ _thread_kern_sig_defer(); + _pthread_mutex_lock(&_atfork_mutex); + + /* Run down atfork prepare handlers. */ + TAILQ_FOREACH_REVERSE(af, &_atfork_list, atfork_head, qe) { + if (af->prepare != NULL) + af->prepare(); + } + /* Fork a new process: */ if ((ret = __sys_fork()) != 0) { - /* Parent process or error. Nothing to do here. */ + /* Run down atfork parent handlers. */ + TAILQ_FOREACH(af, &_atfork_list, qe) { + if (af->parent != NULL) + af->parent(); + } + _pthread_mutex_unlock(&_atfork_mutex); + } else { /* Close the pthread kernel pipe: */ __sys_close(_thread_kern_pipe[0]); @@ -207,8 +222,15 @@ _fork(void) } } } + /* Run down atfork child handlers. */ + TAILQ_FOREACH(af, &_atfork_list, qe) { + if (af->child != NULL) + af->child(); + } + _mutex_reinit(&_atfork_mutex); } + /* * Undefer and handle pending signals, yielding if necessary: */ diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c index fadc277..1cd39b1 100644 --- a/lib/libc_r/uthread/uthread_init.c +++ b/lib/libc_r/uthread/uthread_init.c @@ -437,6 +437,8 @@ _thread_init(void) TAILQ_INIT(&_thread_list); TAILQ_INSERT_HEAD(&_thread_list, _thread_initial, tle); _set_curthread(_thread_initial); + TAILQ_INIT(&_atfork_list); + _pthread_mutex_init(&_atfork_mutex, NULL); /* Initialise the global signal action structure: */ sigfillset(&act.sa_mask); -- cgit v1.1