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