113546Sjulian/*
235509Sjb * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
313546Sjulian * All rights reserved.
413546Sjulian *
513546Sjulian * Redistribution and use in source and binary forms, with or without
613546Sjulian * modification, are permitted provided that the following conditions
713546Sjulian * are met:
813546Sjulian * 1. Redistributions of source code must retain the above copyright
913546Sjulian *    notice, this list of conditions and the following disclaimer.
1013546Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1113546Sjulian *    notice, this list of conditions and the following disclaimer in the
1213546Sjulian *    documentation and/or other materials provided with the distribution.
13165967Simp * 3. Neither the name of the author nor the names of any co-contributors
1413546Sjulian *    may be used to endorse or promote products derived from this software
1513546Sjulian *    without specific prior written permission.
1613546Sjulian *
1713546Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
1813546Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1913546Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2049439Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2113546Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2213546Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2313546Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2413546Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2513546Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2613546Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2713546Sjulian * SUCH DAMAGE.
2813546Sjulian *
2950476Speter * $FreeBSD$
3013546Sjulian */
31174112Sdeischen
32174112Sdeischen#include "namespace.h"
3313546Sjulian#include <errno.h>
3417706Sjulian#include <string.h>
3555194Sdeischen#include <stdlib.h>
3617706Sjulian#include <unistd.h>
3713546Sjulian#include <fcntl.h>
3813546Sjulian#include <pthread.h>
39122075Sdeischen#include <spinlock.h>
40118746Sdavidxu#include <sys/signalvar.h>
41174112Sdeischen#include "un-namespace.h"
42122130Sdeischen
43122130Sdeischen#include "libc_private.h"
44103388Smini#include "thr_private.h"
4513546Sjulian
46174112Sdeischenpid_t	_fork(void);
47174112Sdeischen
4875369Sdeischen__weak_reference(_fork, fork);
4971581Sdeischen
5013546Sjulianpid_t
5156698Sjasone_fork(void)
5213546Sjulian{
53118746Sdavidxu	sigset_t sigset, oldset;
54113658Sdeischen	struct pthread *curthread;
55122075Sdeischen	struct pthread_atfork *af;
56113658Sdeischen	pid_t ret;
57119099Sdavidxu	int errsave;
5813546Sjulian
59113658Sdeischen	curthread = _get_curthread();
6034381Sjb
61139023Sdeischen	if (!_kse_isthreaded()) {
62139023Sdeischen		SIGFILLSET(sigset);
63139023Sdeischen		__sys_sigprocmask(SIG_SETMASK, &sigset, &oldset);
64139023Sdeischen		ret = __sys_fork();
65139023Sdeischen		if (ret == 0)
66139023Sdeischen			/* Child */
67139023Sdeischen			__sys_sigprocmask(SIG_SETMASK, &curthread->sigmask,
68139023Sdeischen			    NULL);
69139023Sdeischen		else
70139023Sdeischen			__sys_sigprocmask(SIG_SETMASK, &oldset, NULL);
71139023Sdeischen		return (ret);
72139023Sdeischen	}
73139023Sdeischen
74118746Sdavidxu	/*
75118746Sdavidxu	 * Masks all signals until we reach a safe point in
76118746Sdavidxu	 * _kse_single_thread, and the signal masks will be
77118746Sdavidxu	 * restored in that function, for M:N thread, all
78118746Sdavidxu	 * signals were already masked in kernel atomically,
79118746Sdavidxu	 * we only need to do this for bound thread.
80118746Sdavidxu	 */
81118746Sdavidxu	if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
82118746Sdavidxu		SIGFILLSET(sigset);
83118746Sdavidxu		__sys_sigprocmask(SIG_SETMASK, &sigset, &oldset);
84118746Sdavidxu	}
85122075Sdeischen
86122075Sdeischen	_pthread_mutex_lock(&_thr_atfork_mutex);
87122075Sdeischen
88122075Sdeischen	/* Run down atfork prepare handlers. */
89122075Sdeischen	TAILQ_FOREACH_REVERSE(af, &_thr_atfork_list, atfork_head, qe) {
90122075Sdeischen		if (af->prepare != NULL)
91122075Sdeischen			af->prepare();
92122075Sdeischen	}
93122075Sdeischen
9413546Sjulian	/* Fork a new process: */
95139023Sdeischen	if (_kse_isthreaded() != 0) {
96154248Sjasone		_malloc_prefork();
97122075Sdeischen	}
98118746Sdavidxu	if ((ret = __sys_fork()) == 0) {
99113658Sdeischen		/* Child process */
100122075Sdeischen		errsave = errno;
101122075Sdeischen
102122075Sdeischen		/* Kernel signal mask is restored in _kse_single_thread */
103113658Sdeischen		_kse_single_thread(curthread);
104122075Sdeischen
105122075Sdeischen		/* Run down atfork child handlers. */
106122075Sdeischen		TAILQ_FOREACH(af, &_thr_atfork_list, qe) {
107122075Sdeischen			if (af->child != NULL)
108122075Sdeischen				af->child();
109122075Sdeischen		}
110122075Sdeischen		_thr_mutex_reinit(&_thr_atfork_mutex);
111118746Sdavidxu	} else {
112154248Sjasone		if (_kse_isthreaded() != 0) {
113154248Sjasone			_malloc_postfork();
114122075Sdeischen		}
115122075Sdeischen		errsave = errno;
116119099Sdavidxu		if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
117118746Sdavidxu			__sys_sigprocmask(SIG_SETMASK, &oldset, NULL);
118122075Sdeischen		}
119122075Sdeischen		/* Run down atfork parent handlers. */
120122075Sdeischen		TAILQ_FOREACH(af, &_thr_atfork_list, qe) {
121122075Sdeischen			if (af->parent != NULL)
122122075Sdeischen				af->parent();
123122075Sdeischen		}
124122075Sdeischen		_pthread_mutex_unlock(&_thr_atfork_mutex);
125118746Sdavidxu	}
126122075Sdeischen	errno = errsave;
12748046Sjb
12813546Sjulian	/* Return the process ID: */
12913546Sjulian	return (ret);
13013546Sjulian}
131