1/* Copyright (C) 2002-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <assert.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <sys/types.h>
23#include <sysdep.h>
24#include <libio/libioP.h>
25#include <tls.h>
26#include <hp-timing.h>
27#include <ldsodefs.h>
28#include <stdio-lock.h>
29#include <atomic.h>
30#include <nptl/pthreadP.h>
31#include <fork.h>
32#include <arch-fork.h>
33#include <futex-internal.h>
34#include <malloc/malloc-internal.h>
35#include <nss/nss_database.h>
36
37static void
38fresetlockfiles (void)
39{
40 _IO_ITER i;
41
42 for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
43 if ((_IO_iter_file (i)->_flags & _IO_USER_LOCK) == 0)
44 _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock));
45}
46
47
48pid_t
49__libc_fork (void)
50{
51 pid_t pid;
52
53 /* Determine if we are running multiple threads. We skip some fork
54 handlers in the single-thread case, to make fork safer to use in
55 signal handlers. POSIX requires that fork is async-signal-safe,
56 but our current fork implementation is not. */
57 bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads);
58
59 __run_fork_handlers (atfork_run_prepare, multiple_threads);
60
61 struct nss_database_data nss_database_data;
62
63 /* If we are not running multiple threads, we do not have to
64 preserve lock state. If fork runs from a signal handler, only
65 async-signal-safe functions can be used in the child. These data
66 structures are only used by unsafe functions, so their state does
67 not matter if fork was called from a signal handler. */
68 if (multiple_threads)
69 {
70 call_function_static_weak (__nss_database_fork_prepare_parent,
71 &nss_database_data);
72
73 _IO_list_lock ();
74
75 /* Acquire malloc locks. This needs to come last because fork
76 handlers may use malloc, and the libio list lock has an
77 indirect malloc dependency as well (via the getdelim
78 function). */
79 call_function_static_weak (__malloc_fork_lock_parent);
80 }
81
82 pid = arch_fork (&THREAD_SELF->tid);
83
84 if (pid == 0)
85 {
86 struct pthread *self = THREAD_SELF;
87
88 /* See __pthread_once. */
89 if (__fork_generation_pointer != NULL)
90 *__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR;
91
92 /* Initialize the robust mutex list setting in the kernel which has
93 been reset during the fork. We do not check for errors because if
94 it fails here, it must have failed at process startup as well and
95 nobody could have used robust mutexes.
96 Before we do that, we have to clear the list of robust mutexes
97 because we do not inherit ownership of mutexes from the parent.
98 We do not have to set self->robust_head.futex_offset since we do
99 inherit the correct value from the parent. We do not need to clear
100 the pending operation because it must have been zero when fork was
101 called. */
102#if __PTHREAD_MUTEX_HAVE_PREV
103 self->robust_prev = &self->robust_head;
104#endif
105 self->robust_head.list = &self->robust_head;
106#ifdef SHARED
107 if (__builtin_expect (__libc_pthread_functions_init, 0))
108 PTHFCT_CALL (ptr_set_robust, (self));
109#else
110 extern __typeof (__nptl_set_robust) __nptl_set_robust
111 __attribute__((weak));
112 if (__builtin_expect (__nptl_set_robust != NULL, 0))
113 __nptl_set_robust (self);
114#endif
115
116 /* Reset the lock state in the multi-threaded case. */
117 if (multiple_threads)
118 {
119 /* Release malloc locks. */
120 call_function_static_weak (__malloc_fork_unlock_child);
121
122 /* Reset the file list. These are recursive mutexes. */
123 fresetlockfiles ();
124
125 /* Reset locks in the I/O code. */
126 _IO_list_resetlock ();
127
128 call_function_static_weak (__nss_database_fork_subprocess,
129 &nss_database_data);
130 }
131
132 /* Reset the lock the dynamic loader uses to protect its data. */
133 __rtld_lock_initialize (GL(dl_load_lock));
134
135 /* Run the handlers registered for the child. */
136 __run_fork_handlers (atfork_run_child, multiple_threads);
137 }
138 else
139 {
140 /* Release acquired locks in the multi-threaded case. */
141 if (multiple_threads)
142 {
143 /* Release malloc locks, parent process variant. */
144 call_function_static_weak (__malloc_fork_unlock_parent);
145
146 /* We execute this even if the 'fork' call failed. */
147 _IO_list_unlock ();
148 }
149
150 /* Run the handlers registered for the parent. */
151 __run_fork_handlers (atfork_run_parent, multiple_threads);
152 }
153
154 return pid;
155}
156weak_alias (__libc_fork, __fork)
157libc_hidden_def (__fork)
158weak_alias (__libc_fork, fork)
159