• 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 <grpc/support/port_platform.h>
16 
17 #include "src/core/lib/event_engine/forkable.h"
18 
19 #include <grpc/support/log.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/lib/config/config_vars.h"
30 
31 namespace grpc_event_engine {
32 namespace experimental {
33 
34 grpc_core::TraceFlag grpc_trace_fork(false, "fork");
35 
36 namespace {
IsForkEnabled()37 bool IsForkEnabled() {
38   static bool enabled = grpc_core::ConfigVars::Get().EnableForkSupport();
39   return enabled;
40 }
41 }  // namespace
42 
RegisterForkable(std::shared_ptr<Forkable> forkable,GRPC_UNUSED void (* prepare)(void),GRPC_UNUSED void (* parent)(void),GRPC_UNUSED void (* child)(void))43 void ObjectGroupForkHandler::RegisterForkable(
44     std::shared_ptr<Forkable> forkable, GRPC_UNUSED void (*prepare)(void),
45     GRPC_UNUSED void (*parent)(void), GRPC_UNUSED void (*child)(void)) {
46   if (IsForkEnabled()) {
47     GPR_ASSERT(!is_forking_);
48     forkables_.emplace_back(forkable);
49 #ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
50     if (!std::exchange(registered_, true)) {
51       pthread_atfork(prepare, parent, child);
52     }
53 #endif  // GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
54   }
55 }
56 
Prefork()57 void ObjectGroupForkHandler::Prefork() {
58   if (IsForkEnabled()) {
59     GPR_ASSERT(!std::exchange(is_forking_, true));
60     GRPC_FORK_TRACE_LOG_STRING("PrepareFork");
61     for (auto it = forkables_.begin(); it != forkables_.end();) {
62       auto shared = it->lock();
63       if (shared) {
64         shared->PrepareFork();
65         ++it;
66       } else {
67         it = forkables_.erase(it);
68       }
69     }
70   }
71 }
72 
PostforkParent()73 void ObjectGroupForkHandler::PostforkParent() {
74   if (IsForkEnabled()) {
75     GPR_ASSERT(is_forking_);
76     GRPC_FORK_TRACE_LOG_STRING("PostforkParent");
77     for (auto it = forkables_.begin(); it != forkables_.end();) {
78       auto shared = it->lock();
79       if (shared) {
80         shared->PostforkParent();
81         ++it;
82       } else {
83         it = forkables_.erase(it);
84       }
85     }
86     is_forking_ = false;
87   }
88 }
89 
PostforkChild()90 void ObjectGroupForkHandler::PostforkChild() {
91   if (IsForkEnabled()) {
92     GPR_ASSERT(is_forking_);
93     GRPC_FORK_TRACE_LOG_STRING("PostforkChild");
94     for (auto it = forkables_.begin(); it != forkables_.end();) {
95       auto shared = it->lock();
96       if (shared) {
97         shared->PostforkChild();
98         ++it;
99       } else {
100         it = forkables_.erase(it);
101       }
102     }
103     is_forking_ = false;
104   }
105 }
106 
107 }  // namespace experimental
108 }  // namespace grpc_event_engine
109