master
 1#include <unistd.h>
 2#include <errno.h>
 3#include "libc.h"
 4#include "lock.h"
 5#include "pthread_impl.h"
 6#include "fork_impl.h"
 7
 8static volatile int *const dummy_lockptr = 0;
 9
10weak_alias(dummy_lockptr, __at_quick_exit_lockptr);
11weak_alias(dummy_lockptr, __atexit_lockptr);
12weak_alias(dummy_lockptr, __gettext_lockptr);
13weak_alias(dummy_lockptr, __locale_lockptr);
14weak_alias(dummy_lockptr, __random_lockptr);
15weak_alias(dummy_lockptr, __sem_open_lockptr);
16weak_alias(dummy_lockptr, __stdio_ofl_lockptr);
17weak_alias(dummy_lockptr, __syslog_lockptr);
18weak_alias(dummy_lockptr, __timezone_lockptr);
19weak_alias(dummy_lockptr, __bump_lockptr);
20
21weak_alias(dummy_lockptr, __vmlock_lockptr);
22
23static volatile int *const *const atfork_locks[] = {
24	&__at_quick_exit_lockptr,
25	&__atexit_lockptr,
26	&__gettext_lockptr,
27	&__locale_lockptr,
28	&__random_lockptr,
29	&__sem_open_lockptr,
30	&__stdio_ofl_lockptr,
31	&__syslog_lockptr,
32	&__timezone_lockptr,
33	&__bump_lockptr,
34};
35
36static void dummy(int x) { }
37weak_alias(dummy, __fork_handler);
38weak_alias(dummy, __malloc_atfork);
39weak_alias(dummy, __aio_atfork);
40weak_alias(dummy, __pthread_key_atfork);
41weak_alias(dummy, __ldso_atfork);
42
43static void dummy_0(void) { }
44weak_alias(dummy_0, __tl_lock);
45weak_alias(dummy_0, __tl_unlock);
46
47pid_t fork(void)
48{
49	sigset_t set;
50	__fork_handler(-1);
51	__block_app_sigs(&set);
52	int need_locks = libc.need_locks > 0;
53	if (need_locks) {
54		__ldso_atfork(-1);
55		__pthread_key_atfork(-1);
56		__aio_atfork(-1);
57		__inhibit_ptc();
58		for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
59			if (*atfork_locks[i]) LOCK(*atfork_locks[i]);
60		__malloc_atfork(-1);
61		__tl_lock();
62	}
63	pthread_t self=__pthread_self(), next=self->next;
64	pid_t ret = _Fork();
65	int errno_save = errno;
66	if (need_locks) {
67		if (!ret) {
68			for (pthread_t td=next; td!=self; td=td->next)
69				td->tid = -1;
70			if (__vmlock_lockptr) {
71				__vmlock_lockptr[0] = 0;
72				__vmlock_lockptr[1] = 0;
73			}
74		}
75		__tl_unlock();
76		__malloc_atfork(!ret);
77		for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
78			if (*atfork_locks[i])
79				if (ret) UNLOCK(*atfork_locks[i]);
80				else **atfork_locks[i] = 0;
81		__release_ptc();
82		if (ret) __aio_atfork(0);
83		__pthread_key_atfork(!ret);
84		__ldso_atfork(!ret);
85	}
86	__restore_sigs(&set);
87	__fork_handler(!ret);
88	if (ret<0) errno = errno_save;
89	return ret;
90}