1 //
2 //
3 // Copyright 2017 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include "src/core/util/fork.h"
20
21 #include <grpc/support/time.h>
22 #include <stdint.h>
23
24 #include "gtest/gtest.h"
25 #include "src/core/util/thd.h"
26 #include "test/core/test_util/test_config.h"
27
TEST(ForkTest,Init)28 TEST(ForkTest, Init) {
29 ASSERT_FALSE(grpc_core::Fork::Enabled());
30
31 // Default fork support (disabled)
32 grpc_core::Fork::GlobalInit();
33 ASSERT_FALSE(grpc_core::Fork::Enabled());
34
35 // Explicitly disabled fork support
36 grpc_core::Fork::Enable(false);
37 grpc_core::Fork::GlobalInit();
38 ASSERT_FALSE(grpc_core::Fork::Enabled());
39
40 // Explicitly enabled fork support
41 grpc_core::Fork::Enable(true);
42 grpc_core::Fork::GlobalInit();
43 ASSERT_TRUE(grpc_core::Fork::Enabled());
44 }
45
46 // This spawns CONCURRENT_TEST_THREADS that last up to
47 // THREAD_DELAY_MS, and checks that the Fork::AwaitThreads()
48 // returns roughly after THREAD_DELAY_MS. The epsilon is high
49 // because tsan threads can take a while to spawn/join.
50 #define THREAD_DELAY_MS 6000
51 #define THREAD_DELAY_EPSILON 1500
52 #define CONCURRENT_TEST_THREADS 10
53
sleeping_thd(void * arg)54 static void sleeping_thd(void* arg) {
55 int64_t sleep_ms = reinterpret_cast<int64_t>(arg);
56 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
57 gpr_time_from_millis(sleep_ms, GPR_TIMESPAN)));
58 }
59
TEST(ForkTest,ThdCount)60 TEST(ForkTest, ThdCount) {
61 // Test no active threads
62 grpc_core::Fork::Enable(true);
63 grpc_core::Fork::GlobalInit();
64 grpc_core::Fork::AwaitThreads();
65
66 grpc_core::Fork::Enable(true);
67 grpc_core::Fork::GlobalInit();
68 grpc_core::Thread thds[CONCURRENT_TEST_THREADS];
69 gpr_timespec est_end_time =
70 gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
71 gpr_time_from_millis(THREAD_DELAY_MS, GPR_TIMESPAN));
72 gpr_timespec tolerance = gpr_time_from_millis(
73 THREAD_DELAY_EPSILON * grpc_test_slowdown_factor(), GPR_TIMESPAN);
74 for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
75 intptr_t sleep_time_ms =
76 (i * THREAD_DELAY_MS) / (CONCURRENT_TEST_THREADS - 1);
77 thds[i] = grpc_core::Thread("grpc_fork_test", sleeping_thd,
78 reinterpret_cast<void*>(sleep_time_ms));
79 thds[i].Start();
80 }
81 grpc_core::Fork::AwaitThreads();
82 gpr_timespec end_time = gpr_now(GPR_CLOCK_REALTIME);
83 for (auto& thd : thds) {
84 thd.Join();
85 }
86 ASSERT_TRUE(gpr_time_similar(end_time, est_end_time, tolerance));
87 }
88
exec_ctx_thread(void * arg)89 static void exec_ctx_thread(void* arg) {
90 bool* exec_ctx_created = static_cast<bool*>(arg);
91 grpc_core::Fork::IncExecCtxCount();
92 *exec_ctx_created = true;
93 }
94
TEST(ForkTest,ExecCount)95 TEST(ForkTest, ExecCount) {
96 grpc_core::Fork::Enable(true);
97 grpc_core::Fork::GlobalInit();
98
99 grpc_core::Fork::IncExecCtxCount();
100 ASSERT_TRUE(grpc_core::Fork::BlockExecCtx());
101 grpc_core::Fork::DecExecCtxCount();
102 grpc_core::Fork::AllowExecCtx();
103
104 grpc_core::Fork::IncExecCtxCount();
105 grpc_core::Fork::IncExecCtxCount();
106 ASSERT_FALSE(grpc_core::Fork::BlockExecCtx());
107 grpc_core::Fork::DecExecCtxCount();
108 grpc_core::Fork::DecExecCtxCount();
109
110 grpc_core::Fork::IncExecCtxCount();
111 ASSERT_TRUE(grpc_core::Fork::BlockExecCtx());
112 grpc_core::Fork::DecExecCtxCount();
113 grpc_core::Fork::AllowExecCtx();
114
115 // Test that block_exec_ctx() blocks grpc_core::Fork::IncExecCtxCount
116 bool exec_ctx_created = false;
117 grpc_core::Thread thd =
118 grpc_core::Thread("grpc_fork_test", exec_ctx_thread, &exec_ctx_created);
119 grpc_core::Fork::IncExecCtxCount();
120 ASSERT_TRUE(grpc_core::Fork::BlockExecCtx());
121 grpc_core::Fork::DecExecCtxCount();
122 thd.Start();
123 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
124 gpr_time_from_seconds(1, GPR_TIMESPAN)));
125 ASSERT_FALSE(exec_ctx_created);
126 grpc_core::Fork::AllowExecCtx();
127 thd.Join(); // This ensure that the call got un-blocked
128 }
129
main(int argc,char ** argv)130 int main(int argc, char** argv) {
131 grpc::testing::TestEnvironment env(&argc, argv);
132 ::testing::InitGoogleTest(&argc, argv);
133 return RUN_ALL_TESTS();
134 }
135