|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <pthread.h> |
|
7 #include <string.h> |
|
8 #include <stdlib.h> |
|
9 #include <time.h> |
|
10 #include <unistd.h> |
|
11 #include <android/log.h> |
|
12 #include <sys/syscall.h> |
|
13 |
|
14 #include "mozilla/Alignment.h" |
|
15 |
|
16 #include <vector> |
|
17 |
|
18 #define NS_EXPORT __attribute__ ((visibility("default"))) |
|
19 |
|
20 #if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID) |
|
21 /* Android doesn't have pthread_atfork(), so we need to use our own. */ |
|
22 struct AtForkFuncs { |
|
23 void (*prepare)(void); |
|
24 void (*parent)(void); |
|
25 void (*child)(void); |
|
26 }; |
|
27 |
|
28 /* jemalloc's initialization calls pthread_atfork. When pthread_atfork (see |
|
29 * further below) stores the corresponding data, it's going to allocate memory, |
|
30 * which will loop back to jemalloc's initialization, leading to a dead-lock. |
|
31 * So, for that specific vector, we use a special allocator that returns a |
|
32 * static buffer for small sizes, and force the initial vector capacity to |
|
33 * a size enough to store one atfork function table. */ |
|
34 template <typename T> |
|
35 struct SpecialAllocator: public std::allocator<T> |
|
36 { |
|
37 SpecialAllocator(): bufUsed(false) {} |
|
38 |
|
39 inline typename std::allocator<T>::pointer allocate(typename std::allocator<T>::size_type n, const void * = 0) { |
|
40 if (!bufUsed && n == 1) { |
|
41 bufUsed = true; |
|
42 return buf.addr(); |
|
43 } |
|
44 return reinterpret_cast<T *>(::operator new(sizeof(T) * n)); |
|
45 } |
|
46 |
|
47 inline void deallocate(typename std::allocator<T>::pointer p, typename std::allocator<T>::size_type n) { |
|
48 if (p == buf.addr()) |
|
49 bufUsed = false; |
|
50 else |
|
51 ::operator delete(p); |
|
52 } |
|
53 |
|
54 template<typename U> |
|
55 struct rebind { |
|
56 typedef SpecialAllocator<U> other; |
|
57 }; |
|
58 |
|
59 private: |
|
60 mozilla::AlignedStorage2<T> buf; |
|
61 bool bufUsed; |
|
62 }; |
|
63 |
|
64 static std::vector<AtForkFuncs, SpecialAllocator<AtForkFuncs> > atfork; |
|
65 #endif |
|
66 |
|
67 #ifdef MOZ_WIDGET_GONK |
|
68 #include "cpuacct.h" |
|
69 #define WRAP(x) x |
|
70 |
|
71 #if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID) |
|
72 extern "C" NS_EXPORT int |
|
73 timer_create(clockid_t, struct sigevent*, timer_t*) |
|
74 { |
|
75 __android_log_print(ANDROID_LOG_ERROR, "BionicGlue", "timer_create not supported!"); |
|
76 abort(); |
|
77 return -1; |
|
78 } |
|
79 #endif |
|
80 |
|
81 #else |
|
82 #define cpuacct_add(x) |
|
83 #define WRAP(x) __wrap_##x |
|
84 #endif |
|
85 |
|
86 #if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID) |
|
87 extern "C" NS_EXPORT int |
|
88 WRAP(pthread_atfork)(void (*prepare)(void), void (*parent)(void), void (*child)(void)) |
|
89 { |
|
90 AtForkFuncs funcs; |
|
91 funcs.prepare = prepare; |
|
92 funcs.parent = parent; |
|
93 funcs.child = child; |
|
94 if (!atfork.capacity()) |
|
95 atfork.reserve(1); |
|
96 atfork.push_back(funcs); |
|
97 return 0; |
|
98 } |
|
99 |
|
100 extern "C" NS_EXPORT pid_t |
|
101 WRAP(fork)(void) |
|
102 { |
|
103 pid_t pid; |
|
104 for (auto it = atfork.rbegin(); |
|
105 it < atfork.rend(); ++it) |
|
106 if (it->prepare) |
|
107 it->prepare(); |
|
108 |
|
109 switch ((pid = syscall(__NR_clone, SIGCHLD, NULL, NULL, NULL, NULL))) { |
|
110 case 0: |
|
111 cpuacct_add(getuid()); |
|
112 for (auto it = atfork.begin(); |
|
113 it < atfork.end(); ++it) |
|
114 if (it->child) |
|
115 it->child(); |
|
116 break; |
|
117 default: |
|
118 for (auto it = atfork.begin(); |
|
119 it < atfork.end(); ++it) |
|
120 if (it->parent) |
|
121 it->parent(); |
|
122 } |
|
123 return pid; |
|
124 } |
|
125 #endif |
|
126 |
|
127 extern "C" NS_EXPORT int |
|
128 WRAP(raise)(int sig) |
|
129 { |
|
130 // Bug 741272: Bionic incorrectly uses kill(), which signals the |
|
131 // process, and thus could signal another thread (and let this one |
|
132 // return "successfully" from raising a fatal signal). |
|
133 // |
|
134 // Bug 943170: POSIX specifies pthread_kill(pthread_self(), sig) as |
|
135 // equivalent to raise(sig), but Bionic also has a bug with these |
|
136 // functions, where a forked child will kill its parent instead. |
|
137 |
|
138 extern pid_t gettid(void); |
|
139 return syscall(__NR_tgkill, getpid(), gettid(), sig); |
|
140 } |
|
141 |
|
142 /* |
|
143 * The following wrappers for PR_Xxx are needed until we can get |
|
144 * PR_DuplicateEnvironment landed in NSPR. |
|
145 * See see bug 772734 and bug 773414. |
|
146 * |
|
147 * We can't #include the pr headers here, and we can't call any of the |
|
148 * PR/PL functions either, so we just reimplemnt using native code. |
|
149 */ |
|
150 |
|
151 static pthread_mutex_t _pr_envLock = PTHREAD_MUTEX_INITIALIZER; |
|
152 |
|
153 extern "C" NS_EXPORT char* |
|
154 __wrap_PR_GetEnv(const char *var) |
|
155 { |
|
156 char *ev; |
|
157 |
|
158 pthread_mutex_lock(&_pr_envLock); |
|
159 ev = getenv(var); |
|
160 pthread_mutex_unlock(&_pr_envLock); |
|
161 return ev; |
|
162 } |
|
163 |
|
164 extern "C" NS_EXPORT int |
|
165 __wrap_PR_SetEnv(const char *string) |
|
166 { |
|
167 int result; |
|
168 |
|
169 if ( !strchr(string, '=')) return(-1); |
|
170 |
|
171 pthread_mutex_lock(&_pr_envLock); |
|
172 result = putenv(string); |
|
173 pthread_mutex_unlock(&_pr_envLock); |
|
174 return (result)? -1 : 0; |
|
175 } |
|
176 |
|
177 extern "C" NS_EXPORT pthread_mutex_t * |
|
178 PR_GetEnvLock(void) |
|
179 { |
|
180 return &_pr_envLock; |
|
181 } |
|
182 |
|
183 /* Amazon Kindle Fire HD's libc provides most of the |
|
184 * functions in string.h as weak symbols, which dlsym |
|
185 * cannot resolve. Thus, we must wrap these functions. |
|
186 * See bug 791419. |
|
187 */ |
|
188 |
|
189 #ifndef MOZ_WIDGET_GONK |
|
190 #include <string.h> |
|
191 extern "C" NS_EXPORT void* __real_memccpy(void * a0, const void * a1, int a2, size_t a3); |
|
192 extern "C" NS_EXPORT void* __real_memchr(const void * a0, int a1, size_t a2); |
|
193 extern "C" NS_EXPORT void* __real_memrchr(const void * a0, int a1, size_t a2); |
|
194 extern "C" NS_EXPORT int __real_memcmp(const void * a0, const void * a1, size_t a2); |
|
195 extern "C" NS_EXPORT void* __real_memcpy(void * a0, const void * a1, size_t a2); |
|
196 extern "C" NS_EXPORT void* __real_memmove(void * a0, const void * a1, size_t a2); |
|
197 extern "C" NS_EXPORT void* __real_memset(void * a0, int a1, size_t a2); |
|
198 extern "C" NS_EXPORT void* __real_memmem(const void * a0, size_t a1, const void * a2, size_t a3); |
|
199 extern "C" NS_EXPORT void __real_memswap(void * a0, void * a1, size_t a2); |
|
200 extern "C" NS_EXPORT char* __real_index(const char * a0, int a1); |
|
201 extern "C" NS_EXPORT char* __real_strchr(const char * a0, int a1); |
|
202 extern "C" NS_EXPORT char* __real_strrchr(const char * a0, int a1); |
|
203 extern "C" NS_EXPORT size_t __real_strlen(const char * a0); |
|
204 extern "C" NS_EXPORT int __real_strcmp(const char * a0, const char * a1); |
|
205 extern "C" NS_EXPORT char* __real_strcpy(char * a0, const char * a1); |
|
206 extern "C" NS_EXPORT char* __real_strcat(char * a0, const char * a1); |
|
207 extern "C" NS_EXPORT int __real_strcasecmp(const char * a0, const char * a1); |
|
208 extern "C" NS_EXPORT int __real_strncasecmp(const char * a0, const char * a1, size_t a2); |
|
209 extern "C" NS_EXPORT char* __real_strstr(const char * a0, const char * a1); |
|
210 extern "C" NS_EXPORT char* __real_strcasestr(const char * a0, const char * a1); |
|
211 extern "C" NS_EXPORT char* __real_strtok(char * a0, const char * a1); |
|
212 extern "C" NS_EXPORT char* __real_strtok_r(char * a0, const char * a1, char** a2); |
|
213 extern "C" NS_EXPORT char* __real_strerror(int a0); |
|
214 extern "C" NS_EXPORT int __real_strerror_r(int a0, char * a1, size_t a2); |
|
215 extern "C" NS_EXPORT size_t __real_strnlen(const char * a0, size_t a1); |
|
216 extern "C" NS_EXPORT char* __real_strncat(char * a0, const char * a1, size_t a2); |
|
217 extern "C" NS_EXPORT int __real_strncmp(const char * a0, const char * a1, size_t a2); |
|
218 extern "C" NS_EXPORT char* __real_strncpy(char * a0, const char * a1, size_t a2); |
|
219 extern "C" NS_EXPORT size_t __real_strlcat(char * a0, const char * a1, size_t a2); |
|
220 extern "C" NS_EXPORT size_t __real_strlcpy(char * a0, const char * a1, size_t a2); |
|
221 extern "C" NS_EXPORT size_t __real_strcspn(const char * a0, const char * a1); |
|
222 extern "C" NS_EXPORT char* __real_strpbrk(const char * a0, const char * a1); |
|
223 extern "C" NS_EXPORT char* __real_strsep(char ** a0, const char * a1); |
|
224 extern "C" NS_EXPORT size_t __real_strspn(const char * a0, const char * a1); |
|
225 extern "C" NS_EXPORT int __real_strcoll(const char * a0, const char * a1); |
|
226 extern "C" NS_EXPORT size_t __real_strxfrm(char * a0, const char * a1, size_t a2); |
|
227 |
|
228 extern "C" NS_EXPORT void* __wrap_memccpy(void * a0, const void * a1, int a2, size_t a3) { return __real_memccpy(a0, a1, a2, a3); } |
|
229 extern "C" NS_EXPORT void* __wrap_memchr(const void * a0, int a1, size_t a2) { return __real_memchr(a0, a1, a2); } |
|
230 extern "C" NS_EXPORT void* __wrap_memrchr(const void * a0, int a1, size_t a2) { return __real_memrchr(a0, a1, a2); } |
|
231 extern "C" NS_EXPORT int __wrap_memcmp(const void * a0, const void * a1, size_t a2) { return __real_memcmp(a0, a1, a2); } |
|
232 extern "C" NS_EXPORT void* __wrap_memcpy(void * a0, const void * a1, size_t a2) { return __real_memcpy(a0, a1, a2); } |
|
233 extern "C" NS_EXPORT void* __wrap_memmove(void * a0, const void * a1, size_t a2) { return __real_memmove(a0, a1, a2); } |
|
234 extern "C" NS_EXPORT void* __wrap_memset(void * a0, int a1, size_t a2) { return __real_memset(a0, a1, a2); } |
|
235 extern "C" NS_EXPORT void* __wrap_memmem(const void * a0, size_t a1, const void * a2, size_t a3) { return __real_memmem(a0, a1, a2, a3); } |
|
236 extern "C" NS_EXPORT void __wrap_memswap(void * a0, void * a1, size_t a2) { __real_memswap(a0, a1, a2); } |
|
237 extern "C" NS_EXPORT char* __wrap_index(const char * a0, int a1) { return __real_index(a0, a1); } |
|
238 extern "C" NS_EXPORT char* __wrap_strchr(const char * a0, int a1) { return __real_strchr(a0, a1); } |
|
239 extern "C" NS_EXPORT char* __wrap_strrchr(const char * a0, int a1) { return __real_strrchr(a0, a1); } |
|
240 extern "C" NS_EXPORT size_t __wrap_strlen(const char * a0) { return __real_strlen(a0); } |
|
241 extern "C" NS_EXPORT int __wrap_strcmp(const char * a0, const char * a1) { return __real_strcmp(a0, a1); } |
|
242 extern "C" NS_EXPORT char* __wrap_strcpy(char * a0, const char * a1) { return __real_strcpy(a0, a1); } |
|
243 extern "C" NS_EXPORT char* __wrap_strcat(char * a0, const char * a1) { return __real_strcat(a0, a1); } |
|
244 extern "C" NS_EXPORT int __wrap_strcasecmp(const char * a0, const char * a1) { return __real_strcasecmp(a0, a1); } |
|
245 extern "C" NS_EXPORT int __wrap_strncasecmp(const char * a0, const char * a1, size_t a2) { return __real_strncasecmp(a0, a1, a2); } |
|
246 extern "C" NS_EXPORT char* __wrap_strstr(const char * a0, const char * a1) { return __real_strstr(a0, a1); } |
|
247 extern "C" NS_EXPORT char* __wrap_strcasestr(const char * a0, const char * a1) { return __real_strcasestr(a0, a1); } |
|
248 extern "C" NS_EXPORT char* __wrap_strtok(char * a0, const char * a1) { return __real_strtok(a0, a1); } |
|
249 extern "C" NS_EXPORT char* __wrap_strtok_r(char * a0, const char * a1, char** a2) { return __real_strtok_r(a0, a1, a2); } |
|
250 extern "C" NS_EXPORT char* __wrap_strerror(int a0) { return __real_strerror(a0); } |
|
251 extern "C" NS_EXPORT int __wrap_strerror_r(int a0, char * a1, size_t a2) { return __real_strerror_r(a0, a1, a2); } |
|
252 extern "C" NS_EXPORT size_t __wrap_strnlen(const char * a0, size_t a1) { return __real_strnlen(a0, a1); } |
|
253 extern "C" NS_EXPORT char* __wrap_strncat(char * a0, const char * a1, size_t a2) { return __real_strncat(a0, a1, a2); } |
|
254 extern "C" NS_EXPORT int __wrap_strncmp(const char * a0, const char * a1, size_t a2) { return __real_strncmp(a0, a1, a2); } |
|
255 extern "C" NS_EXPORT char* __wrap_strncpy(char * a0, const char * a1, size_t a2) { return __real_strncpy(a0, a1, a2); } |
|
256 extern "C" NS_EXPORT size_t __wrap_strlcat(char * a0, const char * a1, size_t a2) { return __real_strlcat(a0, a1, a2); } |
|
257 extern "C" NS_EXPORT size_t __wrap_strlcpy(char * a0, const char * a1, size_t a2) { return __real_strlcpy(a0, a1, a2); } |
|
258 extern "C" NS_EXPORT size_t __wrap_strcspn(const char * a0, const char * a1) { return __real_strcspn(a0, a1); } |
|
259 extern "C" NS_EXPORT char* __wrap_strpbrk(const char * a0, const char * a1) { return __real_strpbrk(a0, a1); } |
|
260 extern "C" NS_EXPORT char* __wrap_strsep(char ** a0, const char * a1) { return __real_strsep(a0, a1); } |
|
261 extern "C" NS_EXPORT size_t __wrap_strspn(const char * a0, const char * a1) { return __real_strspn(a0, a1); } |
|
262 extern "C" NS_EXPORT int __wrap_strcoll(const char * a0, const char * a1) { return __real_strcoll(a0, a1); } |
|
263 extern "C" NS_EXPORT size_t __wrap_strxfrm(char * a0, const char * a1, size_t a2) { return __real_strxfrm(a0, a1, a2); } |
|
264 #endif |