xref: /openbsd-src/lib/libc/sys/w_fork.c (revision fe38b55cb0aae270de3f844146814682e8cd345c)
1*fe38b55cSguenther /*	$OpenBSD: w_fork.c,v 1.3 2016/05/07 19:05:22 guenther Exp $ */
2514a545fSguenther 
3514a545fSguenther /*
4514a545fSguenther  * Copyright (c) 2008 Kurt Miller <kurt@openbsd.org>
5514a545fSguenther  * Copyright (c) 2008 Philip Guenther <guenther@openbsd.org>
6514a545fSguenther  * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>
7514a545fSguenther  * All rights reserved.
8514a545fSguenther  *
9514a545fSguenther  * Redistribution and use in source and binary forms, with or without
10514a545fSguenther  * modification, are permitted provided that the following conditions
11514a545fSguenther  * are met:
12514a545fSguenther  * 1. Redistributions of source code must retain the above copyright
13514a545fSguenther  *    notice, this list of conditions and the following disclaimer.
14514a545fSguenther  * 2. Neither the name of the author nor the names of any co-contributors
15514a545fSguenther  *    may be used to endorse or promote products derived from this software
16514a545fSguenther  *    without specific prior written permission.
17514a545fSguenther  *
18514a545fSguenther  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19514a545fSguenther  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20514a545fSguenther  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21514a545fSguenther  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22514a545fSguenther  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23514a545fSguenther  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24514a545fSguenther  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25514a545fSguenther  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26514a545fSguenther  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27514a545fSguenther  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28514a545fSguenther  * SUCH DAMAGE.
29514a545fSguenther  *
30514a545fSguenther  * $FreeBSD: /repoman/r/ncvs/src/lib/libc_r/uthread/uthread_atfork.c,v 1.1 2004/12/10 03:36:45 grog Exp $
31514a545fSguenther  */
32514a545fSguenther 
33*fe38b55cSguenther #include <tib.h>
34514a545fSguenther #include <unistd.h>
35514a545fSguenther #include "thread_private.h"
36514a545fSguenther #include "atfork.h"
37514a545fSguenther 
38514a545fSguenther pid_t
WRAP(fork)39*fe38b55cSguenther WRAP(fork)(void)
40514a545fSguenther {
41514a545fSguenther 	struct atfork_fn *p;
42514a545fSguenther 	pid_t newid;
43514a545fSguenther 
44514a545fSguenther 	/*
45514a545fSguenther 	 * In the common case the list is empty; remain async-signal-safe
46514a545fSguenther 	 * then by skipping the locking and just forking
47514a545fSguenther 	 */
48*fe38b55cSguenther 	if (TAILQ_FIRST(&_atfork_list) == NULL) {
49*fe38b55cSguenther 		if (_thread_cb.tc_fork != NULL)
50*fe38b55cSguenther 			return _thread_cb.tc_fork();
51*fe38b55cSguenther 		newid = fork();
52*fe38b55cSguenther 		if (newid == 0)
53*fe38b55cSguenther 			TIB_GET()->tib_tid = getthrid();
54*fe38b55cSguenther 		return newid;
55*fe38b55cSguenther 	}
56514a545fSguenther 
57514a545fSguenther 	_ATFORK_LOCK();
58514a545fSguenther 	TAILQ_FOREACH_REVERSE(p, &_atfork_list, atfork_listhead, fn_next)
59514a545fSguenther 		if (p->fn_prepare)
60514a545fSguenther 			p->fn_prepare();
61514a545fSguenther 
62*fe38b55cSguenther 	if (_thread_cb.tc_fork != NULL)
63*fe38b55cSguenther 		newid = _thread_cb.tc_fork();
64*fe38b55cSguenther 	else {
65*fe38b55cSguenther 		newid = fork();
66*fe38b55cSguenther 		if (newid == 0)
67*fe38b55cSguenther 			TIB_GET()->tib_tid = getthrid();
68*fe38b55cSguenther 	}
69514a545fSguenther 
70514a545fSguenther 	if (newid == 0) {
71514a545fSguenther 		TAILQ_FOREACH(p, &_atfork_list, fn_next)
72514a545fSguenther 			if (p->fn_child)
73514a545fSguenther 				p->fn_child();
74514a545fSguenther 	} else {
75514a545fSguenther 		TAILQ_FOREACH(p, &_atfork_list, fn_next)
76514a545fSguenther 			if (p->fn_parent)
77514a545fSguenther 				p->fn_parent();
78514a545fSguenther 	}
79514a545fSguenther 	_ATFORK_UNLOCK();
80514a545fSguenther 
81514a545fSguenther 	return (newid);
82514a545fSguenther }
83*fe38b55cSguenther DEF_WRAP(fork);
84