• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/lib/event_engine/forkable.h"
16 
17 #include <grpc/support/port_platform.h>
18 
19 #include "absl/log/check.h"
20 
21 #ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
22 #include <pthread.h>
23 #endif
24 
25 #include <algorithm>
26 #include <utility>
27 #include <vector>
28 
29 #include "src/core/config/config_vars.h"
30 #include "src/core/lib/debug/trace.h"
31 
32 namespace grpc_event_engine {
33 namespace experimental {
34 
35 namespace {
IsForkEnabled()36 bool IsForkEnabled() {
37   static bool enabled = grpc_core::ConfigVars::Get().EnableForkSupport();
38   return enabled;
39 }
40 }  // namespace
41 
RegisterForkable(std::shared_ptr<Forkable> forkable,GRPC_UNUSED void (* prepare)(void),GRPC_UNUSED void (* parent)(void),GRPC_UNUSED void (* child)(void))42 void ObjectGroupForkHandler::RegisterForkable(
43     std::shared_ptr<Forkable> forkable, GRPC_UNUSED void (*prepare)(void),
44     GRPC_UNUSED void (*parent)(void), GRPC_UNUSED void (*child)(void)) {
45   if (IsForkEnabled()) {
46     CHECK(!is_forking_);
47     forkables_.emplace_back(forkable);
48 #ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
49     if (!std::exchange(registered_, true)) {
50       pthread_atfork(prepare, parent, child);
51     }
52 #endif  // GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
53   }
54 }
55 
Prefork()56 void ObjectGroupForkHandler::Prefork() {
57   if (IsForkEnabled()) {
58     CHECK(!std::exchange(is_forking_, true));
59     GRPC_TRACE_LOG(fork, INFO) << "PrepareFork";
60     for (auto it = forkables_.begin(); it != forkables_.end();) {
61       auto shared = it->lock();
62       if (shared) {
63         shared->PrepareFork();
64         ++it;
65       } else {
66         it = forkables_.erase(it);
67       }
68     }
69   }
70 }
71 
PostforkParent()72 void ObjectGroupForkHandler::PostforkParent() {
73   if (IsForkEnabled()) {
74     CHECK(is_forking_);
75     GRPC_TRACE_LOG(fork, INFO) << "PostforkParent";
76     for (auto it = forkables_.begin(); it != forkables_.end();) {
77       auto shared = it->lock();
78       if (shared) {
79         shared->PostforkParent();
80         ++it;
81       } else {
82         it = forkables_.erase(it);
83       }
84     }
85     is_forking_ = false;
86   }
87 }
88 
PostforkChild()89 void ObjectGroupForkHandler::PostforkChild() {
90   if (IsForkEnabled()) {
91     CHECK(is_forking_);
92     GRPC_TRACE_LOG(fork, INFO) << "PostforkChild";
93     for (auto it = forkables_.begin(); it != forkables_.end();) {
94       auto shared = it->lock();
95       if (shared) {
96         shared->PostforkChild();
97         ++it;
98       } else {
99         it = forkables_.erase(it);
100       }
101     }
102     is_forking_ = false;
103   }
104 }
105 
106 }  // namespace experimental
107 }  // namespace grpc_event_engine
108