• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 static volatile int *const dummy_lockptr = 0;
9 
10 weak_alias(dummy_lockptr, __at_quick_exit_lockptr);
11 weak_alias(dummy_lockptr, __atexit_lockptr);
12 weak_alias(dummy_lockptr, __gettext_lockptr);
13 weak_alias(dummy_lockptr, __locale_lockptr);
14 weak_alias(dummy_lockptr, __random_lockptr);
15 weak_alias(dummy_lockptr, __sem_open_lockptr);
16 weak_alias(dummy_lockptr, __stdio_ofl_lockptr);
17 weak_alias(dummy_lockptr, __syslog_lockptr);
18 weak_alias(dummy_lockptr, __timezone_lockptr);
19 weak_alias(dummy_lockptr, __bump_lockptr);
20 
21 weak_alias(dummy_lockptr, __vmlock_lockptr);
22 
23 static 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 
dummy(int x)36 static void dummy(int x) { }
37 weak_alias(dummy, __fork_handler);
38 weak_alias(dummy, __malloc_atfork);
39 weak_alias(dummy, __aio_atfork);
40 weak_alias(dummy, __pthread_key_atfork);
41 weak_alias(dummy, __ldso_atfork);
42 weak_alias(dummy, __pthread_mutex_unlock_atfork);
43 
dummy_0(void)44 static void dummy_0(void) { }
45 weak_alias(dummy_0, __tl_lock);
46 weak_alias(dummy_0, __tl_unlock);
47 
dummy_get_tl_lock_caller_count(void)48 static struct call_tl_lock *dummy_get_tl_lock_caller_count(void)
49 {
50 	return NULL;
51 }
52 
53 weak_alias(dummy_get_tl_lock_caller_count, get_tl_lock_caller_count);
54 
fork(void)55 pid_t fork(void)
56 {
57 	sigset_t set;
58 	__fork_handler(-1);
59 	__block_app_sigs(&set);
60 	int need_locks = libc.need_locks > 0;
61 	if (need_locks) {
62 		__ldso_atfork(-1);
63 		__pthread_key_atfork(-1);
64 		__aio_atfork(-1);
65 		__inhibit_ptc();
66 		for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
67 			if (*atfork_locks[i]) LOCK(*atfork_locks[i]);
68 		__malloc_atfork(-1);
69 		__tl_lock();
70 		if (get_tl_lock_caller_count()) {
71 			get_tl_lock_caller_count()->fork_tl_lock++;
72 		}
73 	}
74 	pthread_t self=__pthread_self(), next=self->next;
75 	pid_t ret = _Fork();
76 	int errno_save = errno;
77 	if (need_locks) {
78 		if (!ret) {
79 			for (pthread_t td=next; td!=self; td=td->next)
80 				td->tid = -1;
81 			if (__vmlock_lockptr) {
82 				__vmlock_lockptr[0] = 0;
83 				__vmlock_lockptr[1] = 0;
84 			}
85 		}
86 		if (get_tl_lock_caller_count()) {
87 			get_tl_lock_caller_count()->fork_tl_lock--;
88 		}
89 		__tl_unlock();
90 		__malloc_atfork(!ret);
91 		for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
92 			if (*atfork_locks[i])
93 				if (ret) UNLOCK(*atfork_locks[i]);
94 				else **atfork_locks[i] = 0;
95 		__release_ptc();
96 		if (ret) __aio_atfork(0);
97 		__pthread_key_atfork(!ret);
98 		__ldso_atfork(!ret);
99 		__pthread_mutex_unlock_atfork(ret);
100 	}
101 	__restore_sigs(&set);
102 	__fork_handler(!ret);
103 	if (ret<0) errno = errno_save;
104 	return ret;
105 }
106