1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
--- contrib/libs/grpc/src/core/lib/event_engine/forkable.cc
+++ contrib/libs/grpc/src/core/lib/event_engine/forkable.cc
@@ -31,6 +31,20 @@
#include "src/core/lib/debug/trace.h"
+#include "absl/base/thread_annotations.h"
+#include "src/core/lib/gprpp/no_destruct.h"
+#include "src/core/lib/gprpp/sync.h"
+
+namespace {
+grpc_core::NoDestruct<grpc_core::Mutex> g_mu;
+bool g_registered ABSL_GUARDED_BY(g_mu){false};
+using ObjectGroupForkHandler = grpc_event_engine::experimental::ObjectGroupForkHandler;
+grpc_core::NoDestruct<std::vector<ObjectGroupForkHandler*>> g_forkables ABSL_GUARDED_BY(g_mu);
+void PrepareFork();
+void PostforkParent();
+void PostforkChild();
+}
+
namespace grpc_event_engine {
namespace experimental {
@@ -72,8 +86,9 @@ void ObjectGroupForkHandler::RegisterForkable(
GPR_ASSERT(!is_forking_);
forkables_.emplace_back(forkable);
#ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
+ grpc_core::MutexLock lock(g_mu.get());
if (!std::exchange(registered_, true)) {
- pthread_atfork(prepare, parent, child);
+ g_forkables->push_back(this);
}
#endif // GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
}
@@ -134,3 +149,47 @@ void ObjectGroupForkHandler::PostforkChild() {
} // namespace experimental
} // namespace grpc_event_engine
+
+namespace grpc_event_engine {
+namespace experimental {
+void RegisterForkHandlers() {
+ if (IsForkEnabled()) {
+ grpc_core::MutexLock lock(g_mu.get());
+ if (!std::exchange(g_registered, true)) {
+#ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
+ pthread_atfork(PrepareFork, PostforkParent, PostforkChild);
+#endif
+ }
+ }
+}
+}
+}
+
+namespace {
+void PrepareFork() {
+ if (!grpc_event_engine::experimental::IsForkEnabled()) return;
+
+ grpc_core::MutexLock lock(g_mu.get());
+ for (auto it = g_forkables->rbegin(); it != g_forkables->rend(); ++it) {
+ (*it)->Prefork();
+ }
+}
+
+void PostforkParent() {
+ if (!grpc_event_engine::experimental::IsForkEnabled()) return;
+
+ grpc_core::MutexLock lock(g_mu.get());
+ for (auto* forkable : *g_forkables) {
+ forkable->PostforkParent();
+ }
+}
+
+void PostforkChild() {
+ if (!grpc_event_engine::experimental::IsForkEnabled()) return;
+
+ grpc_core::MutexLock lock(g_mu.get());
+ for (auto* forkable : *g_forkables) {
+ forkable->PostforkChild();
+ }
+}
+}
--- contrib/libs/grpc/src/core/lib/event_engine/forkable.h
+++ contrib/libs/grpc/src/core/lib/event_engine/forkable.h
@@ -23,6 +23,15 @@
namespace grpc_event_engine {
namespace experimental {
+// Register fork handlers with the system, enabling fork support.
+//
+// This provides pthread-based support for fork events. Any objects that
+// implement Forkable can register themselves with this system using
+// ManageForkable, and their respective methods will be called upon fork.
+//
+// This should be called once upon grpc_initialization.
+void RegisterForkHandlers();
+
// We've faced flickering crash in grpc during fork.
// Crash is observed in different places before 'execv' is called.
// It is mentioned in https://man7.org/linux/man-pages/man2/fork.2.html
--- contrib/libs/grpc/src/core/lib/surface/init.cc
+++ contrib/libs/grpc/src/core/lib/surface/init.cc
@@ -95,6 +95,7 @@ static void do_basic_init(void) {
gpr_time_init();
grpc_core::PrintExperimentsList();
grpc_core::Fork::GlobalInit();
+ grpc_event_engine::experimental::RegisterForkHandlers();
grpc_fork_handlers_auto_register();
grpc_tracer_init();
grpc_client_channel_global_init_backup_polling();
|