e33b57922f39f6441ae08e0ce7ed2a24c07d8563
[folly.git] / folly / detail / AtFork.cpp
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <folly/detail/AtFork.h>
17
18 #include <list>
19 #include <mutex>
20
21 #include <folly/Exception.h>
22
23 namespace folly {
24
25 namespace detail {
26
27 namespace {
28
29 struct AtForkTask {
30   folly::Function<void()> prepare;
31   folly::Function<void()> parent;
32   folly::Function<void()> child;
33 };
34
35 class AtForkList {
36  public:
37   static AtForkList& instance() {
38     static auto instance = new AtForkList();
39     return *instance;
40   }
41
42   static void prepare() noexcept {
43     instance().tasksLock.lock();
44     auto& tasks = instance().tasks;
45     for (auto task = tasks.rbegin(); task != tasks.rend(); ++task) {
46       task->prepare();
47     }
48   }
49
50   static void parent() noexcept {
51     auto& tasks = instance().tasks;
52     for (auto& task : tasks) {
53       task.parent();
54     }
55     instance().tasksLock.unlock();
56   }
57
58   static void child() noexcept {
59     auto& tasks = instance().tasks;
60     for (auto& task : tasks) {
61       task.child();
62     }
63     instance().tasksLock.unlock();
64   }
65
66   std::mutex tasksLock;
67   std::list<AtForkTask> tasks;
68
69  private:
70   AtForkList() {
71 #if FOLLY_HAVE_PTHREAD_ATFORK
72     int ret = pthread_atfork(
73         &AtForkList::prepare, &AtForkList::parent, &AtForkList::child);
74     checkPosixError(ret, "pthread_atfork failed");
75 #elif !__ANDROID__ && !defined(_MSC_VER)
76 // pthread_atfork is not part of the Android NDK at least as of n9d. If
77 // something is trying to call native fork() directly at all with Android's
78 // process management model, this is probably the least of the problems.
79 //
80 // But otherwise, this is a problem.
81 #warning pthread_atfork unavailable
82 #endif
83   }
84 };
85 } // namespace
86
87 void AtFork::init() {
88   AtForkList::instance();
89 }
90
91 void AtFork::registerHandler(
92     folly::Function<void()> prepare,
93     folly::Function<void()> parent,
94     folly::Function<void()> child) {
95   std::lock_guard<std::mutex> lg(AtForkList::instance().tasksLock);
96   AtForkList::instance().tasks.push_back(
97       {std::move(prepare), std::move(parent), std::move(child)});
98 }
99
100 } // namespace detail
101 } // namespace folly