Backed out changeset 79a1f60d83df (bug 909997) for bustage.
[gecko.git] / mozglue / build / Nuwa.cpp
blobfdc365e91f15822a3b9bc74300b2da93096ab66b
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/. */
6 #include <map>
7 #include <memory>
9 #include <dlfcn.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <setjmp.h>
13 #include <signal.h>
14 #include <poll.h>
15 #include <pthread.h>
16 #include <alloca.h>
17 #include <sys/epoll.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/stat.h>
21 #include <vector>
23 #include "mozilla/LinkedList.h"
24 #include "Nuwa.h"
26 using namespace mozilla;
28 /**
29 * Provides the wrappers to a selected set of pthread and system-level functions
30 * as the basis for implementing Zygote-like preforking mechanism.
33 /**
34 * Real functions for the wrappers.
36 extern "C" {
37 int __real_pthread_create(pthread_t *thread,
38 const pthread_attr_t *attr,
39 void *(*start_routine) (void *),
40 void *arg);
41 int __real_pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
42 int __real_pthread_key_delete(pthread_key_t key);
43 pthread_t __real_pthread_self();
44 int __real_pthread_join(pthread_t thread, void **retval);
45 int __real_epoll_wait(int epfd,
46 struct epoll_event *events,
47 int maxevents,
48 int timeout);
49 int __real_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mtx);
50 int __real_pthread_cond_timedwait(pthread_cond_t *cond,
51 pthread_mutex_t *mtx,
52 const struct timespec *abstime);
53 int __real___pthread_cond_timedwait(pthread_cond_t *cond,
54 pthread_mutex_t *mtx,
55 const struct timespec *abstime,
56 clockid_t clock);
57 int __real_pthread_mutex_lock(pthread_mutex_t *mtx);
58 int __real_poll(struct pollfd *fds, nfds_t nfds, int timeout);
59 int __real_epoll_create(int size);
60 int __real_socketpair(int domain, int type, int protocol, int sv[2]);
61 int __real_pipe2(int __pipedes[2], int flags);
62 int __real_pipe(int __pipedes[2]);
63 int __real_epoll_ctl(int aEpollFd, int aOp, int aFd, struct epoll_event *aEvent);
64 int __real_close(int aFd);
68 #define REAL(s) __real_##s
70 /**
71 * A Nuwa process is started by preparing. After preparing, it waits
72 * for all threads becoming frozen. Then, it is ready while all
73 * threads are frozen.
75 static bool sIsNuwaProcess = false; // This process is a Nuwa process.
76 static bool sIsFreezing = false; // Waiting for all threads getting frozen.
77 static bool sNuwaReady = false; // Nuwa process is ready.
78 static bool sNuwaPendingSpawn = false; // Are there any pending spawn requests?
79 static bool sNuwaForking = false;
81 // Fds of transports of top level protocols.
82 static NuwaProtoFdInfo sProtoFdInfos[NUWA_TOPLEVEL_MAX];
83 static int sProtoFdInfosSize = 0;
85 template <typename T>
86 struct LibcAllocator: public std::allocator<T>
88 LibcAllocator()
90 void* libcHandle = dlopen("libc.so", RTLD_LAZY);
91 mMallocImpl = reinterpret_cast<void*(*)(size_t)>(dlsym(libcHandle, "malloc"));
92 mFreeImpl = reinterpret_cast<void(*)(void*)>(dlsym(libcHandle, "free"));
94 if (!(mMallocImpl && mFreeImpl)) {
95 // libc should be available, or we'll deadlock in using TLSInfoList.
96 abort();
100 inline typename std::allocator<T>::pointer
101 allocate(typename std::allocator<T>::size_type n,
102 const void * = 0)
104 return reinterpret_cast<T *>(mMallocImpl(n));
107 inline void
108 deallocate(typename std::allocator<T>::pointer p,
109 typename std::allocator<T>::size_type n)
111 mFreeImpl(p);
114 template<typename U>
115 struct rebind
117 typedef LibcAllocator<U> other;
119 private:
120 void* (*mMallocImpl)(size_t);
121 void (*mFreeImpl)(void*);
125 * TLSInfoList should use malloc() and free() in libc to avoid the deadlock that
126 * jemalloc calls into __wrap_pthread_mutex_lock() and then deadlocks while
127 * the same thread already acquired sThreadCountLock.
129 typedef std::vector<std::pair<pthread_key_t, void *>,
130 LibcAllocator<std::pair<pthread_key_t, void *> > >
131 TLSInfoList;
134 * The stack size is chosen carefully so the frozen threads doesn't consume too
135 * much memory in the Nuwa process. The threads shouldn't run deep recursive
136 * methods or do large allocations on the stack to avoid stack overflow.
138 #ifndef NUWA_STACK_SIZE
139 #define NUWA_STACK_SIZE (1024 * 32)
140 #endif
142 struct thread_info : public mozilla::LinkedListElement<thread_info> {
143 pthread_t origThreadID;
144 pthread_t recreatedThreadID;
145 pthread_attr_t threadAttr;
146 jmp_buf jmpEnv;
147 jmp_buf retEnv;
149 int flags;
151 void *(*startupFunc)(void *arg);
152 void *startupArg;
154 // The thread specific function to recreate the new thread. It's executed
155 // after the thread is recreated.
156 void (*recrFunc)(void *arg);
157 void *recrArg;
159 TLSInfoList tlsInfo;
161 pthread_mutex_t *reacquireMutex;
162 void *stk;
165 typedef struct thread_info thread_info_t;
167 static thread_info_t *sCurrentRecreatingThread = NULL;
170 * This function runs the custom recreation function registered when calling
171 * NuwaMarkCurrentThread() after thread stack is restored.
173 static void
174 RunCustomRecreation() {
175 thread_info_t *tinfo = sCurrentRecreatingThread;
176 if (tinfo->recrFunc != NULL) {
177 tinfo->recrFunc(tinfo->recrArg);
182 * Every thread should be marked as either TINFO_FLAG_NUWA_SUPPORT or
183 * TINFO_FLAG_NUWA_SKIP, or it means a potential error. We force
184 * Gecko code to mark every single thread to make sure there are no accidents
185 * when recreating threads with Nuwa.
187 * Threads marked as TINFO_FLAG_NUWA_SUPPORT can be checkpointed explicitly, by
188 * calling NuwaCheckpointCurrentThread(), or implicitly when they call into wrapped
189 * functions like pthread_mutex_lock(), epoll_wait(), etc.
190 * TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT denotes the explicitly checkpointed thread.
192 #define TINFO_FLAG_NUWA_SUPPORT 0x1
193 #define TINFO_FLAG_NUWA_SKIP 0x2
194 #define TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT 0x4
196 typedef struct nuwa_construct {
197 void (*construct)(void *);
198 void *arg;
199 } nuwa_construct_t;
201 static std::vector<nuwa_construct_t> sConstructors;
202 static std::vector<nuwa_construct_t> sFinalConstructors;
204 typedef std::map<pthread_key_t, void (*)(void *)> TLSKeySet;
205 static TLSKeySet sTLSKeys;
208 * This mutex is used to block the running threads and freeze their contexts.
209 * PrepareNuwaProcess() is the first one to acquire the lock. Further attempts
210 * to acquire this mutex (in the freeze point macros) will block and freeze the
211 * calling thread.
213 static pthread_mutex_t sThreadFreezeLock = PTHREAD_MUTEX_INITIALIZER;
215 static LinkedList<thread_info_t> sAllThreads;
216 static int sThreadCount = 0;
217 static int sThreadFreezeCount = 0;
219 * This mutex protects the access to thread info:
220 * sAllThreads, sThreadCount, sThreadFreezeCount, sRecreateVIPCount.
222 static pthread_mutex_t sThreadCountLock = PTHREAD_MUTEX_INITIALIZER;
224 * This condition variable lets MakeNuwaProcess() wait until all recreated
225 * threads are frozen.
227 static pthread_cond_t sThreadChangeCond = PTHREAD_COND_INITIALIZER;
230 * This mutex and condition variable is used to serialize the fork requests
231 * from the parent process.
233 static pthread_mutex_t sForkLock = PTHREAD_MUTEX_INITIALIZER;
234 static pthread_cond_t sForkWaitCond = PTHREAD_COND_INITIALIZER;
237 * sForkWaitCondChanged will be reset to false on the IPC thread before
238 * and will be changed to true on the main thread to indicate that the condition
239 * that the IPC thread is waiting for has already changed.
241 static bool sForkWaitCondChanged = false;
244 * This mutex protects the access to sTLSKeys, which keeps track of existing
245 * TLS Keys.
247 static pthread_mutex_t sTLSKeyLock = PTHREAD_MUTEX_INITIALIZER;
248 static int sThreadSkipCount = 0;
250 static thread_info_t *
251 GetThreadInfoInner(pthread_t threadID) {
252 for (thread_info_t *tinfo = sAllThreads.getFirst();
253 tinfo;
254 tinfo = tinfo->getNext()) {
255 if (pthread_equal(tinfo->origThreadID, threadID)) {
256 return tinfo;
260 return NULL;
264 * Get thread info using the specified thread ID.
266 * @return thread_info_t which has threadID == specified threadID
268 static thread_info_t *
269 GetThreadInfo(pthread_t threadID) {
270 if (sIsNuwaProcess) {
271 REAL(pthread_mutex_lock)(&sThreadCountLock);
273 thread_info_t *tinfo = GetThreadInfoInner(threadID);
274 if (sIsNuwaProcess) {
275 pthread_mutex_unlock(&sThreadCountLock);
277 return tinfo;
280 #if !defined(HAVE_THREAD_TLS_KEYWORD)
282 * Get thread info of the current thread.
284 * @return thread_info_t for the current thread.
286 static thread_info_t *
287 GetCurThreadInfo() {
288 pthread_t threadID = REAL(pthread_self)();
289 pthread_t thread_info_t::*threadIDptr =
290 (sIsNuwaProcess ?
291 &thread_info_t::origThreadID :
292 &thread_info_t::recreatedThreadID);
294 REAL(pthread_mutex_lock)(&sThreadCountLock);
295 thread_info_t *tinfo;
296 for (tinfo = sAllThreads.getFirst();
297 tinfo;
298 tinfo = tinfo->getNext()) {
299 if (pthread_equal(tinfo->*threadIDptr, threadID)) {
300 break;
303 pthread_mutex_unlock(&sThreadCountLock);
304 return tinfo;
306 #define CUR_THREAD_INFO GetCurThreadInfo()
307 #define SET_THREAD_INFO(x) /* Nothing to do. */
308 #else
309 // Is not NULL only for threads created by pthread_create() in an Nuwa process.
310 // It is always NULL for the main thread.
311 static __thread thread_info_t *sCurThreadInfo = NULL;
312 #define CUR_THREAD_INFO sCurThreadInfo
313 #define SET_THREAD_INFO(x) do { sCurThreadInfo = (x); } while(0)
314 #endif // HAVE_THREAD_TLS_KEYWORD
317 * Track all epoll fds and handling events.
319 class EpollManager {
320 public:
321 class EpollInfo {
322 public:
323 typedef struct epoll_event Events;
324 typedef std::map<int, Events> EpollEventsMap;
325 typedef EpollEventsMap::iterator iterator;
326 typedef EpollEventsMap::const_iterator const_iterator;
328 EpollInfo(): mBackSize(0) {}
329 EpollInfo(int aBackSize): mBackSize(aBackSize) {}
330 EpollInfo(const EpollInfo &aOther): mEvents(aOther.mEvents)
331 , mBackSize(aOther.mBackSize) {
333 ~EpollInfo() {
334 mEvents.clear();
337 void AddEvents(int aFd, Events &aEvents) {
338 std::pair<iterator, bool> pair =
339 mEvents.insert(std::make_pair(aFd, aEvents));
340 if (!pair.second) {
341 abort();
345 void RemoveEvents(int aFd) {
346 if (!mEvents.erase(aFd)) {
347 abort();
351 void ModifyEvents(int aFd, Events &aEvents) {
352 iterator it = mEvents.find(aFd);
353 if (it == mEvents.end()) {
354 abort();
356 it->second = aEvents;
359 const Events &FindEvents(int aFd) const {
360 const_iterator it = mEvents.find(aFd);
361 if (it == mEvents.end()) {
362 abort();
364 return it->second;
367 int Size() const { return mEvents.size(); }
369 // Iterator with values of <fd, Events> pairs.
370 const_iterator begin() const { return mEvents.begin(); }
371 const_iterator end() const { return mEvents.end(); }
373 int BackSize() const { return mBackSize; }
375 private:
376 EpollEventsMap mEvents;
377 int mBackSize;
379 friend class EpollManager;
382 typedef std::map<int, EpollInfo> EpollInfoMap;
383 typedef EpollInfoMap::iterator iterator;
384 typedef EpollInfoMap::const_iterator const_iterator;
386 public:
387 void AddEpollInfo(int aEpollFd, int aBackSize) {
388 EpollInfo *oldinfo = FindEpollInfo(aEpollFd);
389 if (oldinfo != NULL) {
390 abort();
392 mEpollFdsInfo[aEpollFd] = EpollInfo(aBackSize);
395 EpollInfo *FindEpollInfo(int aEpollFd) {
396 iterator it = mEpollFdsInfo.find(aEpollFd);
397 if (it == mEpollFdsInfo.end()) {
398 return NULL;
400 return &it->second;
403 void RemoveEpollInfo(int aEpollFd) {
404 if (!mEpollFdsInfo.erase(aEpollFd)) {
405 abort();
409 int Size() const { return mEpollFdsInfo.size(); }
411 // Iterator of <epollfd, EpollInfo> pairs.
412 const_iterator begin() const { return mEpollFdsInfo.begin(); }
413 const_iterator end() const { return mEpollFdsInfo.end(); }
415 static EpollManager *Singleton() {
416 if (!sInstance) {
417 sInstance = new EpollManager();
419 return sInstance;
422 static void Shutdown() {
423 if (!sInstance) {
424 abort();
427 delete sInstance;
428 sInstance = NULL;
431 private:
432 static EpollManager *sInstance;
433 ~EpollManager() {
434 mEpollFdsInfo.clear();
437 EpollInfoMap mEpollFdsInfo;
439 EpollManager() {}
442 EpollManager* EpollManager::sInstance;
444 static thread_info_t *
445 thread_info_new(void) {
446 /* link tinfo to sAllThreads */
447 thread_info_t *tinfo = new thread_info_t();
448 tinfo->flags = 0;
449 tinfo->recrFunc = NULL;
450 tinfo->recrArg = NULL;
451 tinfo->recreatedThreadID = 0;
452 tinfo->reacquireMutex = NULL;
453 tinfo->stk = malloc(NUWA_STACK_SIZE);
454 pthread_attr_init(&tinfo->threadAttr);
456 REAL(pthread_mutex_lock)(&sThreadCountLock);
457 // Insert to the tail.
458 sAllThreads.insertBack(tinfo);
460 sThreadCount++;
461 pthread_cond_signal(&sThreadChangeCond);
462 pthread_mutex_unlock(&sThreadCountLock);
464 return tinfo;
467 static void
468 thread_info_cleanup(void *arg) {
469 if (sNuwaForking) {
470 // We shouldn't have any thread exiting when we are forking a new process.
471 abort();
474 thread_info_t *tinfo = (thread_info_t *)arg;
475 pthread_attr_destroy(&tinfo->threadAttr);
477 REAL(pthread_mutex_lock)(&sThreadCountLock);
478 /* unlink tinfo from sAllThreads */
479 tinfo->remove();
481 sThreadCount--;
482 pthread_cond_signal(&sThreadChangeCond);
483 pthread_mutex_unlock(&sThreadCountLock);
485 free(tinfo->stk);
486 delete tinfo;
489 static void *
490 _thread_create_startup(void *arg) {
491 thread_info_t *tinfo = (thread_info_t *)arg;
492 void *r;
494 // Save thread info; especially, stackaddr & stacksize.
495 // Reuse the stack in the new thread.
496 pthread_getattr_np(REAL(pthread_self)(), &tinfo->threadAttr);
498 SET_THREAD_INFO(tinfo);
499 tinfo->origThreadID = REAL(pthread_self)();
501 pthread_cleanup_push(thread_info_cleanup, tinfo);
503 r = tinfo->startupFunc(tinfo->startupArg);
505 if (!sIsNuwaProcess) {
506 return r;
509 pthread_cleanup_pop(1);
511 return r;
514 // reserve STACK_RESERVED_SZ * 4 bytes for thread_recreate_startup().
515 #define STACK_RESERVED_SZ 64
516 #define STACK_SENTINEL(v) ((v)[0])
517 #define STACK_SENTINEL_VALUE(v) ((uint32_t)(v) ^ 0xdeadbeef)
519 static void *
520 thread_create_startup(void *arg) {
522 * Dark Art!! Never try to do the same unless you are ABSOLUTELY sure of
523 * what you are doing!
525 * This function is here for reserving stack space before calling
526 * _thread_create_startup(). see also thread_create_startup();
528 void *r;
529 volatile uint32_t reserved[STACK_RESERVED_SZ];
531 // Reserve stack space.
532 STACK_SENTINEL(reserved) = STACK_SENTINEL_VALUE(reserved);
534 r = _thread_create_startup(arg);
536 // Check if the reservation is enough.
537 if (STACK_SENTINEL(reserved) != STACK_SENTINEL_VALUE(reserved)) {
538 abort(); // Did not reserve enough stack space.
541 thread_info_t *tinfo = CUR_THREAD_INFO;
542 if (!sIsNuwaProcess) {
543 longjmp(tinfo->retEnv, 1);
545 // Never go here!
546 abort();
549 return r;
552 extern "C" MFBT_API int
553 __wrap_pthread_create(pthread_t *thread,
554 const pthread_attr_t *attr,
555 void *(*start_routine) (void *),
556 void *arg) {
557 if (!sIsNuwaProcess) {
558 return REAL(pthread_create)(thread, attr, start_routine, arg);
561 thread_info_t *tinfo = thread_info_new();
562 tinfo->startupFunc = start_routine;
563 tinfo->startupArg = arg;
564 pthread_attr_setstack(&tinfo->threadAttr, tinfo->stk, NUWA_STACK_SIZE);
566 int rv = REAL(pthread_create)(thread,
567 &tinfo->threadAttr,
568 thread_create_startup,
569 tinfo);
570 if (rv) {
571 thread_info_cleanup(tinfo);
572 } else {
573 tinfo->origThreadID = *thread;
576 return rv;
579 // TLS related
582 * Iterates over the existing TLS keys and store the TLS data for the current
583 * thread in tinfo.
585 static void
586 SaveTLSInfo(thread_info_t *tinfo) {
587 REAL(pthread_mutex_lock)(&sTLSKeyLock);
588 tinfo->tlsInfo.clear();
589 for (TLSKeySet::const_iterator it = sTLSKeys.begin();
590 it != sTLSKeys.end();
591 it++) {
592 void *value = pthread_getspecific(it->first);
593 if (value == NULL) {
594 continue;
597 pthread_key_t key = it->first;
598 tinfo->tlsInfo.push_back(TLSInfoList::value_type(key, value));
600 pthread_mutex_unlock(&sTLSKeyLock);
604 * Restores the TLS data for the current thread from tinfo.
606 static void
607 RestoreTLSInfo(thread_info_t *tinfo) {
608 int rv;
610 for (TLSInfoList::const_iterator it = tinfo->tlsInfo.begin();
611 it != tinfo->tlsInfo.end();
612 it++) {
613 pthread_key_t key = it->first;
614 const void *value = it->second;
615 if (pthread_setspecific(key, value)) {
616 abort();
620 SET_THREAD_INFO(tinfo);
621 tinfo->recreatedThreadID = REAL(pthread_self)();
624 extern "C" MFBT_API int
625 __wrap_pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) {
626 int rv = REAL(pthread_key_create)(key, destructor);
627 if (rv != 0) {
628 return rv;
630 REAL(pthread_mutex_lock)(&sTLSKeyLock);
631 sTLSKeys.insert(TLSKeySet::value_type(*key, destructor));
632 pthread_mutex_unlock(&sTLSKeyLock);
633 return 0;
636 extern "C" MFBT_API int
637 __wrap_pthread_key_delete(pthread_key_t key) {
638 if (!sIsNuwaProcess) {
639 return REAL(pthread_key_delete)(key);
641 int rv = REAL(pthread_key_delete)(key);
642 if (rv != 0) {
643 return rv;
645 REAL(pthread_mutex_lock)(&sTLSKeyLock);
646 sTLSKeys.erase(key);
647 pthread_mutex_unlock(&sTLSKeyLock);
648 return 0;
651 extern "C" MFBT_API pthread_t
652 __wrap_pthread_self() {
653 thread_info_t *tinfo = CUR_THREAD_INFO;
654 if (tinfo) {
655 // For recreated thread, masquerade as the original thread in the Nuwa
656 // process.
657 return tinfo->origThreadID;
659 return REAL(pthread_self)();
662 extern "C" MFBT_API int
663 __wrap_pthread_join(pthread_t thread, void **retval) {
664 thread_info_t *tinfo = GetThreadInfo(thread);
665 if (tinfo == NULL) {
666 return REAL(pthread_join)(thread, retval);
668 // pthread_join() need to use the real thread ID in the spawned process.
669 return REAL(pthread_join)(tinfo->recreatedThreadID, retval);
673 * The following are used to synchronize between the main thread and the
674 * thread being recreated. The main thread will wait until the thread is woken
675 * up from the freeze points or the blocking intercepted functions and then
676 * proceed to recreate the next frozen thread.
678 * In thread recreation, the main thread recreates the frozen threads one by
679 * one. The recreated threads will be "gated" until the main thread "opens the
680 * gate" to let them run freely as if they were created from scratch. The VIP
681 * threads gets the chance to run first after their thread stacks are recreated
682 * (using longjmp()) so they can adjust their contexts to a valid, consistent
683 * state. The threads frozen waiting for pthread condition variables are VIP
684 * threads. After woken up they need to run first to make the associated mutex
685 * in a valid state to maintain the semantics of the intercepted function calls
686 * (like pthread_cond_wait()).
689 // Used to synchronize the main thread and the thread being recreated so that
690 // only one thread is allowed to be recreated at a time.
691 static pthread_mutex_t sRecreateWaitLock = PTHREAD_MUTEX_INITIALIZER;
692 // Used to block recreated threads until the main thread "opens the gate".
693 static pthread_mutex_t sRecreateGateLock = PTHREAD_MUTEX_INITIALIZER;
694 // Used to block the main thread from "opening the gate" until all VIP threads
695 // have been recreated.
696 static pthread_mutex_t sRecreateVIPGateLock = PTHREAD_MUTEX_INITIALIZER;
697 static pthread_cond_t sRecreateVIPCond = PTHREAD_COND_INITIALIZER;
698 static int sRecreateVIPCount = 0;
699 static int sRecreateGatePassed = 0;
702 * Thread recreation macros.
704 * The following macros are used in the forked process to synchronize and
705 * control the progress of thread recreation.
707 * 1. RECREATE_START() is first called in the beginning of thread
708 * recreation to set sRecreateWaitLock and sRecreateGateLock in locked
709 * state.
710 * 2. For each frozen thread:
711 * 2.1. RECREATE_BEFORE() to set the thread being recreated.
712 * 2.2. thread_recreate() to recreate the frozen thread.
713 * 2.3. Main thread calls RECREATE_WAIT() to wait on sRecreateWaitLock until
714 * the thread is recreated from the freeze point and calls
715 * RECREATE_CONTINUE() to release sRecreateWaitLock.
716 * 2.3. Non-VIP threads are blocked on RECREATE_GATE(). VIP threads calls
717 * RECREATE_PASS_VIP() to mark that a VIP thread is successfully
718 * recreated and then is blocked by calling RECREATE_GATE_VIP().
719 * 3. RECREATE_WAIT_ALL_VIP() to wait until all VIP threads passed, that is,
720 * VIP threads already has their contexts (mainly pthread mutex) in a valid
721 * state.
722 * 4. RECREATE_OPEN_GATE() to unblock threads blocked by sRecreateGateLock.
723 * 5. RECREATE_FINISH() to complete thread recreation.
725 #define RECREATE_START() \
726 do { \
727 REAL(pthread_mutex_lock)(&sRecreateWaitLock); \
728 REAL(pthread_mutex_lock)(&sRecreateGateLock); \
729 } while(0)
730 #define RECREATE_BEFORE(info) do { sCurrentRecreatingThread = info; } while(0)
731 #define RECREATE_WAIT() REAL(pthread_mutex_lock)(&sRecreateWaitLock)
732 #define RECREATE_CONTINUE() do { \
733 RunCustomRecreation(); \
734 pthread_mutex_unlock(&sRecreateWaitLock); \
735 } while(0)
736 #define RECREATE_FINISH() pthread_mutex_unlock(&sRecreateWaitLock)
737 #define RECREATE_GATE() \
738 do { \
739 REAL(pthread_mutex_lock)(&sRecreateGateLock); \
740 sRecreateGatePassed++; \
741 pthread_mutex_unlock(&sRecreateGateLock); \
742 } while(0)
743 #define RECREATE_OPEN_GATE() pthread_mutex_unlock(&sRecreateGateLock)
744 #define RECREATE_GATE_VIP() \
745 do { \
746 REAL(pthread_mutex_lock)(&sRecreateGateLock); \
747 pthread_mutex_unlock(&sRecreateGateLock); \
748 } while(0)
749 #define RECREATE_PASS_VIP() \
750 do { \
751 REAL(pthread_mutex_lock)(&sRecreateVIPGateLock); \
752 sRecreateGatePassed++; \
753 pthread_cond_signal(&sRecreateVIPCond); \
754 pthread_mutex_unlock(&sRecreateVIPGateLock); \
755 } while(0)
756 #define RECREATE_WAIT_ALL_VIP() \
757 do { \
758 REAL(pthread_mutex_lock)(&sRecreateVIPGateLock); \
759 while(sRecreateGatePassed < sRecreateVIPCount) { \
760 REAL(pthread_cond_wait)(&sRecreateVIPCond, \
761 &sRecreateVIPGateLock); \
763 pthread_mutex_unlock(&sRecreateVIPGateLock); \
764 } while(0)
767 * Thread freeze points. Note that the freeze points are implemented as macros
768 * so as not to garble the content of the stack after setjmp().
770 * In the nuwa process, when a thread supporting nuwa calls a wrapper
771 * function, freeze point 1 setjmp()s to save the state. We only allow the
772 * thread to be frozen in the wrapper functions. If thread freezing is not
773 * enabled yet, the wrapper functions act like their wrapped counterparts,
774 * except for the extra actions in the freeze points. If thread freezing is
775 * enabled, the thread will be frozen by calling one of the wrapper functions.
776 * The threads can be frozen in any of the following points:
778 * 1) Freeze point 1: this is the point where we setjmp() in the nuwa process
779 * and longjmp() in the spawned process. If freezing is enabled, then the
780 * current thread blocks by acquiring an already locked mutex,
781 * sThreadFreezeLock.
782 * 2) The wrapped function: the function that might block waiting for some
783 * resource or condition.
784 * 3) Freeze point 2: blocks the current thread by acquiring sThreadFreezeLock.
785 * If freezing is not enabled then revert the counter change in freeze
786 * point 1.
788 #define THREAD_FREEZE_POINT1() \
789 bool freezeCountChg = false; \
790 bool recreated = false; \
791 volatile bool freezePoint2 = false; \
792 thread_info_t *tinfo; \
793 if (sIsNuwaProcess && \
794 (tinfo = CUR_THREAD_INFO) && \
795 (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) && \
796 !(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { \
797 if (!setjmp(tinfo->jmpEnv)) { \
798 REAL(pthread_mutex_lock)(&sThreadCountLock); \
799 SaveTLSInfo(tinfo); \
800 sThreadFreezeCount++; \
801 freezeCountChg = true; \
802 pthread_cond_signal(&sThreadChangeCond); \
803 pthread_mutex_unlock(&sThreadCountLock); \
805 if (sIsFreezing) { \
806 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
807 /* Never return from the pthread_mutex_lock() call. */ \
808 abort(); \
810 } else { \
811 RECREATE_CONTINUE(); \
812 RECREATE_GATE(); \
813 freezeCountChg = false; \
814 recreated = true; \
818 #define THREAD_FREEZE_POINT1_VIP() \
819 bool freezeCountChg = false; \
820 bool recreated = false; \
821 volatile bool freezePoint1 = false; \
822 volatile bool freezePoint2 = false; \
823 thread_info_t *tinfo; \
824 if (sIsNuwaProcess && \
825 (tinfo = CUR_THREAD_INFO) && \
826 (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) && \
827 !(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { \
828 if (!setjmp(tinfo->jmpEnv)) { \
829 REAL(pthread_mutex_lock)(&sThreadCountLock); \
830 SaveTLSInfo(tinfo); \
831 sThreadFreezeCount++; \
832 sRecreateVIPCount++; \
833 freezeCountChg = true; \
834 pthread_cond_signal(&sThreadChangeCond); \
835 pthread_mutex_unlock(&sThreadCountLock); \
837 if (sIsFreezing) { \
838 freezePoint1 = true; \
839 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
840 /* Never return from the pthread_mutex_lock() call. */ \
841 abort(); \
843 } else { \
844 freezeCountChg = false; \
845 recreated = true; \
849 #define THREAD_FREEZE_POINT2() \
850 if (freezeCountChg) { \
851 REAL(pthread_mutex_lock)(&sThreadCountLock); \
852 if (sNuwaReady && sIsNuwaProcess) { \
853 pthread_mutex_unlock(&sThreadCountLock); \
854 freezePoint2 = true; \
855 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
856 /* Never return from the pthread_mutex_lock() call. */ \
857 abort(); \
859 sThreadFreezeCount--; \
860 pthread_cond_signal(&sThreadChangeCond); \
861 pthread_mutex_unlock(&sThreadCountLock); \
864 #define THREAD_FREEZE_POINT2_VIP() \
865 if (freezeCountChg) { \
866 REAL(pthread_mutex_lock)(&sThreadCountLock); \
867 if (sNuwaReady && sIsNuwaProcess) { \
868 pthread_mutex_unlock(&sThreadCountLock); \
869 freezePoint2 = true; \
870 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
871 /* Never return from the pthread_mutex_lock() call. */ \
872 abort(); \
874 sThreadFreezeCount--; \
875 sRecreateVIPCount--; \
876 pthread_cond_signal(&sThreadChangeCond); \
877 pthread_mutex_unlock(&sThreadCountLock); \
881 * Wrapping the blocking functions: epoll_wait(), poll(), pthread_mutex_lock(),
882 * pthread_cond_wait() and pthread_cond_timedwait():
884 * These functions are wrapped by the above freeze point macros. Once a new
885 * process is forked, the recreated thread will be blocked in one of the wrapper
886 * functions. When recreating the thread, we longjmp() to
887 * THREAD_FREEZE_POINT1() to recover the thread stack. Care must be taken to
888 * maintain the semantics of the wrapped function:
890 * - epoll_wait() and poll(): just retry the function.
891 * - pthread_mutex_lock(): don't lock if frozen at freeze point 2 (lock is
892 * already acquired).
893 * - pthread_cond_wait() and pthread_cond_timedwait(): if the thread is frozen
894 * waiting the condition variable, the mutex is already released, we need to
895 * reacquire the mutex before calling the wrapped function again so the mutex
896 * will be in a valid state.
899 extern "C" MFBT_API int
900 __wrap_epoll_wait(int epfd,
901 struct epoll_event *events,
902 int maxevents,
903 int timeout) {
904 int rv;
906 THREAD_FREEZE_POINT1();
907 rv = REAL(epoll_wait)(epfd, events, maxevents, timeout);
908 THREAD_FREEZE_POINT2();
910 return rv;
913 extern "C" MFBT_API int
914 __wrap_pthread_cond_wait(pthread_cond_t *cond,
915 pthread_mutex_t *mtx) {
916 int rv = 0;
918 THREAD_FREEZE_POINT1_VIP();
919 if (freezePoint2) {
920 RECREATE_CONTINUE();
921 RECREATE_PASS_VIP();
922 RECREATE_GATE_VIP();
923 return rv;
925 if (recreated && mtx) {
926 if (!freezePoint1 && pthread_mutex_trylock(mtx)) {
927 // The thread was frozen in pthread_cond_wait() after releasing mtx in the
928 // Nuwa process. In recreating this thread, We failed to reacquire mtx
929 // with the pthread_mutex_trylock() call, that is, mtx was acquired by
930 // another thread. Because of this, we need the main thread's help to
931 // reacquire mtx so that it will be in a valid state.
932 tinfo->reacquireMutex = mtx;
934 RECREATE_CONTINUE();
935 RECREATE_PASS_VIP();
937 rv = REAL(pthread_cond_wait)(cond, mtx);
938 if (recreated && mtx) {
939 // We still need to be gated as not to acquire another mutex associated with
940 // another VIP thread and interfere with it.
941 RECREATE_GATE_VIP();
943 THREAD_FREEZE_POINT2_VIP();
945 return rv;
948 extern "C" MFBT_API int
949 __wrap_pthread_cond_timedwait(pthread_cond_t *cond,
950 pthread_mutex_t *mtx,
951 const struct timespec *abstime) {
952 int rv = 0;
954 THREAD_FREEZE_POINT1_VIP();
955 if (freezePoint2) {
956 RECREATE_CONTINUE();
957 RECREATE_PASS_VIP();
958 RECREATE_GATE_VIP();
959 return rv;
961 if (recreated && mtx) {
962 if (!freezePoint1 && pthread_mutex_trylock(mtx)) {
963 tinfo->reacquireMutex = mtx;
965 RECREATE_CONTINUE();
966 RECREATE_PASS_VIP();
968 rv = REAL(pthread_cond_timedwait)(cond, mtx, abstime);
969 if (recreated && mtx) {
970 RECREATE_GATE_VIP();
972 THREAD_FREEZE_POINT2_VIP();
974 return rv;
977 extern "C" int __pthread_cond_timedwait(pthread_cond_t *cond,
978 pthread_mutex_t *mtx,
979 const struct timespec *abstime,
980 clockid_t clock);
982 extern "C" MFBT_API int
983 __wrap___pthread_cond_timedwait(pthread_cond_t *cond,
984 pthread_mutex_t *mtx,
985 const struct timespec *abstime,
986 clockid_t clock) {
987 int rv = 0;
989 THREAD_FREEZE_POINT1_VIP();
990 if (freezePoint2) {
991 RECREATE_CONTINUE();
992 RECREATE_PASS_VIP();
993 RECREATE_GATE_VIP();
994 return rv;
996 if (recreated && mtx) {
997 if (!freezePoint1 && pthread_mutex_trylock(mtx)) {
998 tinfo->reacquireMutex = mtx;
1000 RECREATE_CONTINUE();
1001 RECREATE_PASS_VIP();
1003 rv = REAL(__pthread_cond_timedwait)(cond, mtx, abstime, clock);
1004 if (recreated && mtx) {
1005 RECREATE_GATE_VIP();
1007 THREAD_FREEZE_POINT2_VIP();
1009 return rv;
1012 extern "C" MFBT_API int
1013 __wrap_pthread_mutex_lock(pthread_mutex_t *mtx) {
1014 int rv = 0;
1016 THREAD_FREEZE_POINT1();
1017 if (freezePoint2) {
1018 return rv;
1020 rv = REAL(pthread_mutex_lock)(mtx);
1021 THREAD_FREEZE_POINT2();
1023 return rv;
1026 extern "C" MFBT_API int
1027 __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
1028 int rv;
1030 THREAD_FREEZE_POINT1();
1031 rv = REAL(poll)(fds, nfds, timeout);
1032 THREAD_FREEZE_POINT2();
1034 return rv;
1037 extern "C" MFBT_API int
1038 __wrap_epoll_create(int size) {
1039 int epollfd = REAL(epoll_create)(size);
1041 if (!sIsNuwaProcess) {
1042 return epollfd;
1045 if (epollfd >= 0) {
1046 EpollManager::Singleton()->AddEpollInfo(epollfd, size);
1049 return epollfd;
1053 * Wrapping the functions to create file descriptor pairs. In the child process
1054 * FD pairs are created for intra-process signaling. The generation of FD pairs
1055 * need to be tracked in the nuwa process so they can be recreated in the
1056 * spawned process.
1058 struct FdPairInfo {
1059 enum {
1060 kPipe,
1061 kSocketpair
1062 } call;
1064 int FDs[2];
1065 int flags;
1066 int domain;
1067 int type;
1068 int protocol;
1072 * Protects the access to sSingalFds.
1074 static pthread_mutex_t sSignalFdLock = PTHREAD_MUTEX_INITIALIZER;
1075 static std::vector<FdPairInfo> sSignalFds;
1077 extern "C" MFBT_API int
1078 __wrap_socketpair(int domain, int type, int protocol, int sv[2])
1080 int rv = REAL(socketpair)(domain, type, protocol, sv);
1082 if (!sIsNuwaProcess || rv < 0) {
1083 return rv;
1086 REAL(pthread_mutex_lock)(&sSignalFdLock);
1087 FdPairInfo signalFd;
1088 signalFd.call = FdPairInfo::kSocketpair;
1089 signalFd.FDs[0] = sv[0];
1090 signalFd.FDs[1] = sv[1];
1091 signalFd.domain = domain;
1092 signalFd.type = type;
1093 signalFd.protocol = protocol;
1095 sSignalFds.push_back(signalFd);
1096 pthread_mutex_unlock(&sSignalFdLock);
1098 return rv;
1101 extern "C" MFBT_API int
1102 __wrap_pipe2(int __pipedes[2], int flags)
1104 int rv = REAL(pipe2)(__pipedes, flags);
1105 if (!sIsNuwaProcess || rv < 0) {
1106 return rv;
1109 REAL(pthread_mutex_lock)(&sSignalFdLock);
1110 FdPairInfo signalFd;
1111 signalFd.call = FdPairInfo::kPipe;
1112 signalFd.FDs[0] = __pipedes[0];
1113 signalFd.FDs[1] = __pipedes[1];
1114 signalFd.flags = flags;
1115 sSignalFds.push_back(signalFd);
1116 pthread_mutex_unlock(&sSignalFdLock);
1117 return rv;
1120 extern "C" MFBT_API int
1121 __wrap_pipe(int __pipedes[2])
1123 return __wrap_pipe2(__pipedes, 0);
1126 static void
1127 DupeSingleFd(int newFd, int origFd)
1129 struct stat sb;
1130 if (fstat(origFd, &sb)) {
1131 // Maybe the original FD is closed.
1132 return;
1134 int fd = fcntl(origFd, F_GETFD);
1135 int fl = fcntl(origFd, F_GETFL);
1136 dup2(newFd, origFd);
1137 fcntl(origFd, F_SETFD, fd);
1138 fcntl(origFd, F_SETFL, fl);
1139 REAL(close)(newFd);
1142 extern "C" MFBT_API void
1143 ReplaceSignalFds()
1145 for (std::vector<FdPairInfo>::iterator it = sSignalFds.begin();
1146 it < sSignalFds.end(); ++it) {
1147 int fds[2];
1148 int rc = 0;
1149 switch (it->call) {
1150 case FdPairInfo::kPipe:
1151 rc = REAL(pipe2)(fds, it->flags);
1152 break;
1153 case FdPairInfo::kSocketpair:
1154 rc = REAL(socketpair)(it->domain, it->type, it->protocol, fds);
1155 break;
1156 default:
1157 continue;
1160 if (rc == 0) {
1161 DupeSingleFd(fds[0], it->FDs[0]);
1162 DupeSingleFd(fds[1], it->FDs[1]);
1167 extern "C" MFBT_API int
1168 __wrap_epoll_ctl(int aEpollFd, int aOp, int aFd, struct epoll_event *aEvent) {
1169 int rv = REAL(epoll_ctl)(aEpollFd, aOp, aFd, aEvent);
1171 if (!sIsNuwaProcess || rv == -1) {
1172 return rv;
1175 EpollManager::EpollInfo *info =
1176 EpollManager::Singleton()->FindEpollInfo(aEpollFd);
1177 if (info == NULL) {
1178 abort();
1181 switch(aOp) {
1182 case EPOLL_CTL_ADD:
1183 info->AddEvents(aFd, *aEvent);
1184 break;
1186 case EPOLL_CTL_MOD:
1187 info->ModifyEvents(aFd, *aEvent);
1188 break;
1190 case EPOLL_CTL_DEL:
1191 info->RemoveEvents(aFd);
1192 break;
1194 default:
1195 abort();
1198 return rv;
1201 // XXX: thinker: Maybe, we should also track dup, dup2, and other functions.
1202 extern "C" MFBT_API int
1203 __wrap_close(int aFd) {
1204 int rv = REAL(close)(aFd);
1205 if (!sIsNuwaProcess || rv == -1) {
1206 return rv;
1209 EpollManager::EpollInfo *info =
1210 EpollManager::Singleton()->FindEpollInfo(aFd);
1211 if (info) {
1212 EpollManager::Singleton()->RemoveEpollInfo(aFd);
1215 return rv;
1218 static void *
1219 thread_recreate_startup(void *arg) {
1221 * Dark Art!! Never do the same unless you are ABSOLUTELY sure what you are
1222 * doing!
1224 * The stack space collapsed by this frame had been reserved by
1225 * thread_create_startup(). And thread_create_startup() will
1226 * return immediately after returning from real start routine, so
1227 * all collapsed values does not affect the result.
1229 * All outer frames of thread_create_startup() and
1230 * thread_recreate_startup() are equivalent, so
1231 * thread_create_startup() will return successfully.
1233 thread_info_t *tinfo = (thread_info_t *)arg;
1235 RestoreTLSInfo(tinfo);
1237 if (setjmp(tinfo->retEnv) != 0) {
1238 return NULL;
1241 // longjump() to recreate the stack on the new thread.
1242 longjmp(tinfo->jmpEnv, 1);
1244 // Never go here!
1245 abort();
1247 return NULL;
1251 * Recreate the context given by tinfo at a new thread.
1253 static void
1254 thread_recreate(thread_info_t *tinfo) {
1255 pthread_t thread;
1257 // Note that the thread_recreate_startup() runs on the stack specified by
1258 // tinfo.
1259 pthread_create(&thread, &tinfo->threadAttr, thread_recreate_startup, tinfo);
1263 * Recreate all threads in a process forked from an Nuwa process.
1265 static void
1266 RecreateThreads() {
1267 sIsNuwaProcess = false;
1268 sIsFreezing = false;
1270 // Run registered constructors.
1271 for (std::vector<nuwa_construct_t>::iterator ctr = sConstructors.begin();
1272 ctr != sConstructors.end();
1273 ctr++) {
1274 (*ctr).construct((*ctr).arg);
1276 sConstructors.clear();
1278 REAL(pthread_mutex_lock)(&sThreadCountLock);
1279 thread_info_t *tinfo = sAllThreads.getFirst();
1280 pthread_mutex_unlock(&sThreadCountLock);
1282 RECREATE_START();
1283 while (tinfo != NULL) {
1284 if (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) {
1285 RECREATE_BEFORE(tinfo);
1286 thread_recreate(tinfo);
1287 RECREATE_WAIT();
1288 if (tinfo->reacquireMutex) {
1289 REAL(pthread_mutex_lock)(tinfo->reacquireMutex);
1291 } else if(!(tinfo->flags & TINFO_FLAG_NUWA_SKIP)) {
1292 // An unmarked thread is found other than the main thread.
1294 // All threads should be marked as one of SUPPORT or SKIP, or
1295 // abort the process to make sure all threads in the Nuwa
1296 // process are Nuwa-aware.
1297 abort();
1300 tinfo = tinfo->getNext();
1302 RECREATE_WAIT_ALL_VIP();
1303 RECREATE_OPEN_GATE();
1305 RECREATE_FINISH();
1307 // Run registered final constructors.
1308 for (std::vector<nuwa_construct_t>::iterator ctr = sFinalConstructors.begin();
1309 ctr != sFinalConstructors.end();
1310 ctr++) {
1311 (*ctr).construct((*ctr).arg);
1313 sFinalConstructors.clear();
1316 extern "C" {
1319 * Recreate all epoll fds and restore status; include all events.
1321 static void
1322 RecreateEpollFds() {
1323 EpollManager *man = EpollManager::Singleton();
1325 for (EpollManager::const_iterator info_it = man->begin();
1326 info_it != man->end();
1327 info_it++) {
1328 int epollfd = info_it->first;
1329 const EpollManager::EpollInfo *info = &info_it->second;
1331 int fdflags = fcntl(epollfd, F_GETFD);
1332 if (fdflags == -1) {
1333 abort();
1335 int fl = fcntl(epollfd, F_GETFL);
1336 if (fl == -1) {
1337 abort();
1340 int newepollfd = REAL(epoll_create)(info->BackSize());
1341 if (newepollfd == -1) {
1342 abort();
1344 int rv = REAL(close)(epollfd);
1345 if (rv == -1) {
1346 abort();
1348 rv = dup2(newepollfd, epollfd);
1349 if (rv == -1) {
1350 abort();
1352 rv = REAL(close)(newepollfd);
1353 if (rv == -1) {
1354 abort();
1357 rv = fcntl(epollfd, F_SETFD, fdflags);
1358 if (rv == -1) {
1359 abort();
1361 rv = fcntl(epollfd, F_SETFL, fl);
1362 if (rv == -1) {
1363 abort();
1366 for (EpollManager::EpollInfo::const_iterator events_it = info->begin();
1367 events_it != info->end();
1368 events_it++) {
1369 int fd = events_it->first;
1370 epoll_event events;
1371 events = events_it->second;
1372 rv = REAL(epoll_ctl)(epollfd, EPOLL_CTL_ADD, fd, &events);
1373 if (rv == -1) {
1374 abort();
1379 // Shutdown EpollManager. It won't be needed in the spawned process.
1380 EpollManager::Shutdown();
1384 * Fix IPC to make it ready.
1386 * Especially, fix ContentChild.
1388 static void
1389 ReplaceIPC(NuwaProtoFdInfo *aInfoList, int aInfoSize) {
1390 int i;
1391 int rv;
1393 for (i = 0; i < aInfoSize; i++) {
1394 int fd = fcntl(aInfoList[i].originFd, F_GETFD);
1395 if (fd == -1) {
1396 abort();
1399 int fl = fcntl(aInfoList[i].originFd, F_GETFL);
1400 if (fl == -1) {
1401 abort();
1404 rv = dup2(aInfoList[i].newFds[NUWA_NEWFD_CHILD], aInfoList[i].originFd);
1405 if (rv == -1) {
1406 abort();
1409 rv = fcntl(aInfoList[i].originFd, F_SETFD, fd);
1410 if (rv == -1) {
1411 abort();
1414 rv = fcntl(aInfoList[i].originFd, F_SETFL, fl);
1415 if (rv == -1) {
1416 abort();
1422 * Add a new content process at the chrome process.
1424 static void
1425 AddNewProcess(pid_t pid, NuwaProtoFdInfo *aInfoList, int aInfoSize) {
1426 static bool (*AddNewIPCProcess)(pid_t, NuwaProtoFdInfo *, int) = NULL;
1428 if (AddNewIPCProcess == NULL) {
1429 AddNewIPCProcess = (bool (*)(pid_t, NuwaProtoFdInfo *, int))
1430 dlsym(RTLD_DEFAULT, "AddNewIPCProcess");
1432 AddNewIPCProcess(pid, aInfoList, aInfoSize);
1435 static void
1436 PrepareProtoSockets(NuwaProtoFdInfo *aInfoList, int aInfoSize) {
1437 int i;
1438 int rv;
1440 for (i = 0; i < aInfoSize; i++) {
1441 rv = REAL(socketpair)(PF_UNIX, SOCK_STREAM, 0, aInfoList[i].newFds);
1442 if (rv == -1) {
1443 abort();
1448 static void
1449 CloseAllProtoSockets(NuwaProtoFdInfo *aInfoList, int aInfoSize) {
1450 int i;
1452 for (i = 0; i < aInfoSize; i++) {
1453 REAL(close)(aInfoList[i].newFds[0]);
1454 REAL(close)(aInfoList[i].newFds[1]);
1459 * Fork a new process that is ready for running IPC.
1461 * @return the PID of the new process.
1463 static int
1464 ForkIPCProcess() {
1465 int pid;
1467 REAL(pthread_mutex_lock)(&sForkLock);
1469 PrepareProtoSockets(sProtoFdInfos, sProtoFdInfosSize);
1471 sNuwaForking = true;
1472 pid = fork();
1473 sNuwaForking = false;
1474 if (pid == -1) {
1475 abort();
1478 if (pid > 0) {
1479 // in the parent
1480 AddNewProcess(pid, sProtoFdInfos, sProtoFdInfosSize);
1481 CloseAllProtoSockets(sProtoFdInfos, sProtoFdInfosSize);
1482 } else {
1483 // in the child
1484 #ifdef NUWA_DEBUG_CHILD_PROCESS
1485 fprintf(stderr, "\n\n DEBUG ME @%d\n\n", getpid());
1486 sleep(15);
1487 #endif
1488 ReplaceSignalFds();
1489 ReplaceIPC(sProtoFdInfos, sProtoFdInfosSize);
1490 RecreateEpollFds();
1491 RecreateThreads();
1492 CloseAllProtoSockets(sProtoFdInfos, sProtoFdInfosSize);
1495 sForkWaitCondChanged = true;
1496 pthread_cond_signal(&sForkWaitCond);
1497 pthread_mutex_unlock(&sForkLock);
1499 return pid;
1503 * Prepare for spawning a new process. Called on the IPC thread.
1505 MFBT_API void
1506 NuwaSpawnPrepare() {
1507 REAL(pthread_mutex_lock)(&sForkLock);
1509 sForkWaitCondChanged = false; // Will be modified on the main thread.
1513 * Let IPC thread wait until fork action on the main thread has completed.
1515 MFBT_API void
1516 NuwaSpawnWait() {
1517 while (!sForkWaitCondChanged) {
1518 REAL(pthread_cond_wait)(&sForkWaitCond, &sForkLock);
1520 pthread_mutex_unlock(&sForkLock);
1524 * Spawn a new process. If not ready for spawn (still waiting for some threads
1525 * to freeze), postpone the spawn request until ready.
1527 * @return the pid of the new process, or 0 if not ready.
1529 MFBT_API pid_t
1530 NuwaSpawn() {
1531 if (gettid() != getpid()) {
1532 // Not the main thread.
1533 abort();
1536 pid_t pid = 0;
1538 if (sNuwaReady) {
1539 pid = ForkIPCProcess();
1540 } else {
1541 sNuwaPendingSpawn = true;
1544 return pid;
1548 * Prepare to freeze the Nuwa-supporting threads.
1550 MFBT_API void
1551 PrepareNuwaProcess() {
1552 sIsNuwaProcess = true;
1553 // Explicitly ignore SIGCHLD so we don't have to call watpid() to reap
1554 // dead child processes.
1555 signal(SIGCHLD, SIG_IGN);
1557 // Make marked threads block in one freeze point.
1558 REAL(pthread_mutex_lock)(&sThreadFreezeLock);
1561 // Make current process as a Nuwa process.
1562 MFBT_API void
1563 MakeNuwaProcess() {
1564 void (*GetProtoFdInfos)(NuwaProtoFdInfo *, int, int *) = NULL;
1565 void (*OnNuwaProcessReady)() = NULL;
1566 sIsFreezing = true;
1568 REAL(pthread_mutex_lock)(&sThreadCountLock);
1570 // wait until all threads are frozen.
1571 while ((sThreadFreezeCount + sThreadSkipCount) != sThreadCount) {
1572 REAL(pthread_cond_wait)(&sThreadChangeCond, &sThreadCountLock);
1575 GetProtoFdInfos = (void (*)(NuwaProtoFdInfo *, int, int *))
1576 dlsym(RTLD_DEFAULT, "GetProtoFdInfos");
1577 GetProtoFdInfos(sProtoFdInfos, NUWA_TOPLEVEL_MAX, &sProtoFdInfosSize);
1579 sNuwaReady = true;
1581 pthread_mutex_unlock(&sThreadCountLock);
1583 OnNuwaProcessReady = (void (*)())dlsym(RTLD_DEFAULT, "OnNuwaProcessReady");
1584 OnNuwaProcessReady();
1586 if (sNuwaPendingSpawn) {
1587 sNuwaPendingSpawn = false;
1588 NuwaSpawn();
1593 * Mark the current thread as supporting Nuwa. The thread will be recreated in
1594 * the spawned process.
1596 MFBT_API void
1597 NuwaMarkCurrentThread(void (*recreate)(void *), void *arg) {
1598 if (!sIsNuwaProcess) {
1599 return;
1602 thread_info_t *tinfo = CUR_THREAD_INFO;
1603 if (tinfo == NULL) {
1604 abort();
1607 tinfo->flags |= TINFO_FLAG_NUWA_SUPPORT;
1608 tinfo->recrFunc = recreate;
1609 tinfo->recrArg = arg;
1613 * Mark the current thread as not supporting Nuwa. Don't recreate this thread in
1614 * the spawned process.
1616 MFBT_API void
1617 NuwaSkipCurrentThread() {
1618 if (!sIsNuwaProcess) return;
1620 thread_info_t *tinfo = CUR_THREAD_INFO;
1621 if (tinfo == NULL) {
1622 abort();
1625 if (!(tinfo->flags & TINFO_FLAG_NUWA_SKIP)) {
1626 sThreadSkipCount++;
1628 tinfo->flags |= TINFO_FLAG_NUWA_SKIP;
1632 * Force to freeze the current thread.
1634 * This method does not return in Nuwa process. It returns for the
1635 * recreated thread.
1637 MFBT_API void
1638 NuwaFreezeCurrentThread() {
1639 thread_info_t *tinfo = CUR_THREAD_INFO;
1640 if (sIsNuwaProcess &&
1641 (tinfo = CUR_THREAD_INFO) &&
1642 (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT)) {
1643 if (!setjmp(tinfo->jmpEnv)) {
1644 REAL(pthread_mutex_lock)(&sThreadCountLock);
1645 SaveTLSInfo(tinfo);
1646 sThreadFreezeCount++;
1647 pthread_cond_signal(&sThreadChangeCond);
1648 pthread_mutex_unlock(&sThreadCountLock);
1650 REAL(pthread_mutex_lock)(&sThreadFreezeLock);
1651 } else {
1652 RECREATE_CONTINUE();
1653 RECREATE_GATE();
1659 * The caller of NuwaCheckpointCurrentThread() is at the line it wishes to
1660 * return after the thread is recreated.
1662 * The checkpointed thread will restart at the calling line of
1663 * NuwaCheckpointCurrentThread(). This macro returns true in the Nuwa process
1664 * and false on the recreated thread in the forked process.
1666 * NuwaCheckpointCurrentThread() is implemented as a macro so we can place the
1667 * setjmp() call in the calling method without changing its stack pointer. This
1668 * is essential for not corrupting the stack when the calling thread continues
1669 * to request the main thread for forking a new process. The caller of
1670 * NuwaCheckpointCurrentThread() should not return before the process forking
1671 * finishes.
1673 * @return true for Nuwa process, and false in the forked process.
1675 MFBT_API jmp_buf*
1676 NuwaCheckpointCurrentThread1() {
1677 thread_info_t *tinfo = CUR_THREAD_INFO;
1678 if (sIsNuwaProcess &&
1679 (tinfo = CUR_THREAD_INFO) &&
1680 (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT)) {
1681 return &tinfo->jmpEnv;
1683 abort();
1684 return nullptr;
1687 MFBT_API bool
1688 NuwaCheckpointCurrentThread2(int setjmpCond) {
1689 thread_info_t *tinfo = CUR_THREAD_INFO;
1690 if (setjmpCond == 0) {
1691 REAL(pthread_mutex_lock)(&sThreadCountLock);
1692 if (!(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) {
1693 tinfo->flags |= TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT;
1694 SaveTLSInfo(tinfo);
1695 sThreadFreezeCount++;
1697 pthread_cond_signal(&sThreadChangeCond);
1698 pthread_mutex_unlock(&sThreadCountLock);
1699 return true;
1701 RECREATE_CONTINUE();
1702 RECREATE_GATE();
1703 return false; // Recreated thread.
1707 * Register methods to be invoked before recreating threads in the spawned
1708 * process.
1710 MFBT_API void
1711 NuwaAddConstructor(void (*construct)(void *), void *arg) {
1712 nuwa_construct_t ctr;
1713 ctr.construct = construct;
1714 ctr.arg = arg;
1715 sConstructors.push_back(ctr);
1719 * Register methods to be invoked after recreating threads in the spawned
1720 * process.
1722 MFBT_API void
1723 NuwaAddFinalConstructor(void (*construct)(void *), void *arg) {
1724 nuwa_construct_t ctr;
1725 ctr.construct = construct;
1726 ctr.arg = arg;
1727 sFinalConstructors.push_back(ctr);
1731 * @return if the current process is the nuwa process.
1733 MFBT_API bool
1734 IsNuwaProcess() {
1735 return sIsNuwaProcess;
1739 * @return if the nuwa process is ready for spawning new processes.
1741 MFBT_API bool
1742 IsNuwaReady() {
1743 return sNuwaReady;
1746 } // extern "C"