xref: /minix3/lib/libc/gen/pthread_atfork.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: pthread_atfork.c,v 1.10 2015/01/20 18:31:25 christos Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras  * Copyright (c) 2002 The NetBSD Foundation, Inc.
52fe8fb19SBen Gras  * All rights reserved.
62fe8fb19SBen Gras  *
72fe8fb19SBen Gras  * This code is derived from software contributed to The NetBSD Foundation
82fe8fb19SBen Gras  * by Nathan J. Williams.
92fe8fb19SBen Gras  *
102fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
112fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
122fe8fb19SBen Gras  * are met:
132fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
142fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
152fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
162fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
172fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
182fe8fb19SBen Gras  *
192fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
202fe8fb19SBen Gras  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
212fe8fb19SBen Gras  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
222fe8fb19SBen Gras  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
232fe8fb19SBen Gras  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
242fe8fb19SBen Gras  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
252fe8fb19SBen Gras  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
262fe8fb19SBen Gras  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
272fe8fb19SBen Gras  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
282fe8fb19SBen Gras  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
292fe8fb19SBen Gras  * POSSIBILITY OF SUCH DAMAGE.
302fe8fb19SBen Gras  */
312fe8fb19SBen Gras 
322fe8fb19SBen Gras #include <sys/cdefs.h>
332fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
34*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: pthread_atfork.c,v 1.10 2015/01/20 18:31:25 christos Exp $");
352fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
362fe8fb19SBen Gras 
372fe8fb19SBen Gras #include "namespace.h"
382fe8fb19SBen Gras 
392fe8fb19SBen Gras #include <errno.h>
402fe8fb19SBen Gras #include <stdlib.h>
412fe8fb19SBen Gras #include <unistd.h>
422fe8fb19SBen Gras #include <sys/queue.h>
432fe8fb19SBen Gras #include "reentrant.h"
442fe8fb19SBen Gras 
452fe8fb19SBen Gras #ifdef __weak_alias
462fe8fb19SBen Gras __weak_alias(pthread_atfork, _pthread_atfork)
472fe8fb19SBen Gras __weak_alias(fork, _fork)
482fe8fb19SBen Gras #endif /* __weak_alias */
492fe8fb19SBen Gras 
50f14fb602SLionel Sambuc pid_t	__fork(void);	/* XXX */
512fe8fb19SBen Gras 
522fe8fb19SBen Gras struct atfork_callback {
532fe8fb19SBen Gras 	SIMPLEQ_ENTRY(atfork_callback) next;
542fe8fb19SBen Gras 	void (*fn)(void);
552fe8fb19SBen Gras };
562fe8fb19SBen Gras 
572fe8fb19SBen Gras /*
582fe8fb19SBen Gras  * Hypothetically, we could protect the queues with a rwlock which is
592fe8fb19SBen Gras  * write-locked by pthread_atfork() and read-locked by fork(), but
602fe8fb19SBen Gras  * since the intended use of the functions is obtaining locks to hold
612fe8fb19SBen Gras  * across the fork, forking is going to be serialized anyway.
622fe8fb19SBen Gras  */
632fe8fb19SBen Gras static struct atfork_callback atfork_builtin;
64*0a6a1f1dSLionel Sambuc #ifdef _REENTRANT
652fe8fb19SBen Gras static mutex_t atfork_lock = MUTEX_INITIALIZER;
66*0a6a1f1dSLionel Sambuc #endif
672fe8fb19SBen Gras SIMPLEQ_HEAD(atfork_callback_q, atfork_callback);
682fe8fb19SBen Gras 
692fe8fb19SBen Gras static struct atfork_callback_q prepareq = SIMPLEQ_HEAD_INITIALIZER(prepareq);
702fe8fb19SBen Gras static struct atfork_callback_q parentq = SIMPLEQ_HEAD_INITIALIZER(parentq);
712fe8fb19SBen Gras static struct atfork_callback_q childq = SIMPLEQ_HEAD_INITIALIZER(childq);
722fe8fb19SBen Gras 
732fe8fb19SBen Gras static struct atfork_callback *
af_alloc(void)742fe8fb19SBen Gras af_alloc(void)
752fe8fb19SBen Gras {
762fe8fb19SBen Gras 
772fe8fb19SBen Gras 	if (atfork_builtin.fn == NULL)
782fe8fb19SBen Gras 		return &atfork_builtin;
792fe8fb19SBen Gras 
802fe8fb19SBen Gras 	return malloc(sizeof(atfork_builtin));
812fe8fb19SBen Gras }
822fe8fb19SBen Gras 
832fe8fb19SBen Gras static void
af_free(struct atfork_callback * af)842fe8fb19SBen Gras af_free(struct atfork_callback *af)
852fe8fb19SBen Gras {
862fe8fb19SBen Gras 
872fe8fb19SBen Gras 	if (af != &atfork_builtin)
882fe8fb19SBen Gras 		free(af);
892fe8fb19SBen Gras }
902fe8fb19SBen Gras 
912fe8fb19SBen Gras int
pthread_atfork(void (* prepare)(void),void (* parent)(void),void (* child)(void))922fe8fb19SBen Gras pthread_atfork(void (*prepare)(void), void (*parent)(void),
932fe8fb19SBen Gras     void (*child)(void))
942fe8fb19SBen Gras {
952fe8fb19SBen Gras 	struct atfork_callback *newprepare, *newparent, *newchild;
962fe8fb19SBen Gras 
972fe8fb19SBen Gras 	newprepare = newparent = newchild = NULL;
982fe8fb19SBen Gras 
992fe8fb19SBen Gras 	mutex_lock(&atfork_lock);
1002fe8fb19SBen Gras 	if (prepare != NULL) {
1012fe8fb19SBen Gras 		newprepare = af_alloc();
1022fe8fb19SBen Gras 		if (newprepare == NULL) {
1032fe8fb19SBen Gras 			mutex_unlock(&atfork_lock);
1042fe8fb19SBen Gras 			return ENOMEM;
1052fe8fb19SBen Gras 		}
1062fe8fb19SBen Gras 		newprepare->fn = prepare;
1072fe8fb19SBen Gras 	}
1082fe8fb19SBen Gras 
1092fe8fb19SBen Gras 	if (parent != NULL) {
1102fe8fb19SBen Gras 		newparent = af_alloc();
1112fe8fb19SBen Gras 		if (newparent == NULL) {
1122fe8fb19SBen Gras 			if (newprepare != NULL)
1132fe8fb19SBen Gras 				af_free(newprepare);
1142fe8fb19SBen Gras 			mutex_unlock(&atfork_lock);
1152fe8fb19SBen Gras 			return ENOMEM;
1162fe8fb19SBen Gras 		}
1172fe8fb19SBen Gras 		newparent->fn = parent;
1182fe8fb19SBen Gras 	}
1192fe8fb19SBen Gras 
1202fe8fb19SBen Gras 	if (child != NULL) {
1212fe8fb19SBen Gras 		newchild = af_alloc();
1222fe8fb19SBen Gras 		if (newchild == NULL) {
1232fe8fb19SBen Gras 			if (newprepare != NULL)
1242fe8fb19SBen Gras 				af_free(newprepare);
1252fe8fb19SBen Gras 			if (newparent != NULL)
1262fe8fb19SBen Gras 				af_free(newparent);
1272fe8fb19SBen Gras 			mutex_unlock(&atfork_lock);
1282fe8fb19SBen Gras 			return ENOMEM;
1292fe8fb19SBen Gras 		}
1302fe8fb19SBen Gras 		newchild->fn = child;
1312fe8fb19SBen Gras 	}
1322fe8fb19SBen Gras 
1332fe8fb19SBen Gras 	/*
1342fe8fb19SBen Gras 	 * The order in which the functions are called is specified as
1352fe8fb19SBen Gras 	 * LIFO for the prepare handler and FIFO for the others; insert
1362fe8fb19SBen Gras 	 * at the head and tail as appropriate so that SIMPLEQ_FOREACH()
1372fe8fb19SBen Gras 	 * produces the right order.
1382fe8fb19SBen Gras 	 */
1392fe8fb19SBen Gras 	if (prepare)
1402fe8fb19SBen Gras 		SIMPLEQ_INSERT_HEAD(&prepareq, newprepare, next);
1412fe8fb19SBen Gras 	if (parent)
1422fe8fb19SBen Gras 		SIMPLEQ_INSERT_TAIL(&parentq, newparent, next);
1432fe8fb19SBen Gras 	if (child)
1442fe8fb19SBen Gras 		SIMPLEQ_INSERT_TAIL(&childq, newchild, next);
1452fe8fb19SBen Gras 	mutex_unlock(&atfork_lock);
1462fe8fb19SBen Gras 
1472fe8fb19SBen Gras 	return 0;
1482fe8fb19SBen Gras }
1492fe8fb19SBen Gras 
1502fe8fb19SBen Gras pid_t
fork(void)1512fe8fb19SBen Gras fork(void)
1522fe8fb19SBen Gras {
1532fe8fb19SBen Gras 	struct atfork_callback *iter;
1542fe8fb19SBen Gras 	pid_t ret;
1552fe8fb19SBen Gras 
1562fe8fb19SBen Gras 	mutex_lock(&atfork_lock);
1572fe8fb19SBen Gras 	SIMPLEQ_FOREACH(iter, &prepareq, next)
1582fe8fb19SBen Gras 		(*iter->fn)();
1592fe8fb19SBen Gras 
1602fe8fb19SBen Gras 	ret = __fork();
1612fe8fb19SBen Gras 
1622fe8fb19SBen Gras 	if (ret != 0) {
1632fe8fb19SBen Gras 		/*
1642fe8fb19SBen Gras 		 * We are the parent. It doesn't matter here whether
1652fe8fb19SBen Gras 		 * the fork call succeeded or failed.
1662fe8fb19SBen Gras 		 */
1672fe8fb19SBen Gras 		SIMPLEQ_FOREACH(iter, &parentq, next)
1682fe8fb19SBen Gras 			(*iter->fn)();
1692fe8fb19SBen Gras 		mutex_unlock(&atfork_lock);
1702fe8fb19SBen Gras 	} else {
1712fe8fb19SBen Gras 		/* We are the child */
1722fe8fb19SBen Gras 		SIMPLEQ_FOREACH(iter, &childq, next)
1732fe8fb19SBen Gras 			(*iter->fn)();
1742fe8fb19SBen Gras 		/*
1752fe8fb19SBen Gras 		 * Note: We are explicitly *not* unlocking
1762fe8fb19SBen Gras 		 * atfork_lock.  Unlocking atfork_lock is problematic,
1772fe8fb19SBen Gras 		 * because if any threads in the parent blocked on it
1782fe8fb19SBen Gras 		 * between the initial lock and the fork() syscall,
1792fe8fb19SBen Gras 		 * unlocking in the child will try to schedule
1802fe8fb19SBen Gras 		 * threads, and either the internal mutex interlock or
1812fe8fb19SBen Gras 		 * the runqueue spinlock could have been held at the
1822fe8fb19SBen Gras 		 * moment of fork(). Since the other threads do not
1832fe8fb19SBen Gras 		 * exist in this process, the spinlock will never be
1842fe8fb19SBen Gras 		 * unlocked, and we would wedge.
1852fe8fb19SBen Gras 		 * Instead, we reinitialize atfork_lock, since we know
1862fe8fb19SBen Gras 		 * that the state of the atfork lists is consistent here,
1872fe8fb19SBen Gras 		 * and that there are no other threads to be affected by
1882fe8fb19SBen Gras 		 * the forcible cleaning of the queue.
1892fe8fb19SBen Gras 		 * This permits double-forking to work, although
1902fe8fb19SBen Gras 		 * it requires knowing that it's "safe" to initialize
1912fe8fb19SBen Gras 		 * a locked mutex in this context.
1922fe8fb19SBen Gras 		 *
1932fe8fb19SBen Gras 		 * The problem exists for users of this interface,
1942fe8fb19SBen Gras 		 * too, since the intented use of pthread_atfork() is
1952fe8fb19SBen Gras 		 * to acquire locks across the fork call to ensure
1962fe8fb19SBen Gras 		 * that the child sees consistent state. There's not
1972fe8fb19SBen Gras 		 * much that can usefully be done in a child handler,
1982fe8fb19SBen Gras 		 * and conventional wisdom discourages using them, but
1992fe8fb19SBen Gras 		 * they're part of the interface, so here we are...
2002fe8fb19SBen Gras 		 */
2012fe8fb19SBen Gras 		mutex_init(&atfork_lock, NULL);
2022fe8fb19SBen Gras 	}
2032fe8fb19SBen Gras 
2042fe8fb19SBen Gras 	return ret;
2052fe8fb19SBen Gras }
206