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/lib/gprpp/fork.h" 20 21 #include "src/core/lib/gprpp/thd.h" 22 #include "test/core/util/test_config.h" 23 24 static void test_init() { 25 GPR_ASSERT(!grpc_core::Fork::Enabled()); 26 27 // Default fork support (disabled) 28 grpc_core::Fork::GlobalInit(); 29 GPR_ASSERT(!grpc_core::Fork::Enabled()); 30 grpc_core::Fork::GlobalShutdown(); 31 32 // Explicitly disabled fork support 33 grpc_core::Fork::Enable(false); 34 grpc_core::Fork::GlobalInit(); 35 GPR_ASSERT(!grpc_core::Fork::Enabled()); 36 grpc_core::Fork::GlobalShutdown(); 37 38 // Explicitly enabled fork support 39 grpc_core::Fork::Enable(true); 40 grpc_core::Fork::GlobalInit(); 41 GPR_ASSERT(grpc_core::Fork::Enabled()); 42 grpc_core::Fork::GlobalShutdown(); 43 } 44 45 // This spawns CONCURRENT_TEST_THREADS that last up to 46 // THREAD_DELAY_MS, and checks that the Fork::AwaitThreads() 47 // returns roughly after THREAD_DELAY_MS. The epsilon is high 48 // because tsan threads can take a while to spawn/join. 49 #define THREAD_DELAY_MS 6000 50 #define THREAD_DELAY_EPSILON 1500 51 #define CONCURRENT_TEST_THREADS 100 52 53 static void sleeping_thd(void* arg) { 54 int64_t sleep_ms = (int64_t)arg; 55 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), 56 gpr_time_from_millis(sleep_ms, GPR_TIMESPAN))); 57 } 58 59 static void test_thd_count() { 60 // Test no active threads 61 grpc_core::Fork::Enable(true); 62 grpc_core::Fork::GlobalInit(); 63 grpc_core::Fork::AwaitThreads(); 64 grpc_core::Fork::GlobalShutdown(); 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 = 73 gpr_time_from_millis(THREAD_DELAY_EPSILON, 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] = 78 grpc_core::Thread("grpc_fork_test", sleeping_thd, (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 GPR_ASSERT(gpr_time_similar(end_time, est_end_time, tolerance)); 87 grpc_core::Fork::GlobalShutdown(); 88 } 89 90 static void exec_ctx_thread(void* arg) { 91 bool* exec_ctx_created = (bool*)arg; 92 grpc_core::Fork::IncExecCtxCount(); 93 *exec_ctx_created = true; 94 } 95 96 static void test_exec_count() { 97 grpc_core::Fork::Enable(true); 98 grpc_core::Fork::GlobalInit(); 99 100 grpc_core::Fork::IncExecCtxCount(); 101 GPR_ASSERT(grpc_core::Fork::BlockExecCtx()); 102 grpc_core::Fork::DecExecCtxCount(); 103 grpc_core::Fork::AllowExecCtx(); 104 105 grpc_core::Fork::IncExecCtxCount(); 106 grpc_core::Fork::IncExecCtxCount(); 107 GPR_ASSERT(!grpc_core::Fork::BlockExecCtx()); 108 grpc_core::Fork::DecExecCtxCount(); 109 grpc_core::Fork::DecExecCtxCount(); 110 111 grpc_core::Fork::IncExecCtxCount(); 112 GPR_ASSERT(grpc_core::Fork::BlockExecCtx()); 113 grpc_core::Fork::DecExecCtxCount(); 114 grpc_core::Fork::AllowExecCtx(); 115 116 // Test that block_exec_ctx() blocks grpc_core::Fork::IncExecCtxCount 117 bool exec_ctx_created = false; 118 grpc_core::Thread thd = 119 grpc_core::Thread("grpc_fork_test", exec_ctx_thread, &exec_ctx_created); 120 grpc_core::Fork::IncExecCtxCount(); 121 GPR_ASSERT(grpc_core::Fork::BlockExecCtx()); 122 grpc_core::Fork::DecExecCtxCount(); 123 thd.Start(); 124 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), 125 gpr_time_from_seconds(1, GPR_TIMESPAN))); 126 GPR_ASSERT(!exec_ctx_created); 127 grpc_core::Fork::AllowExecCtx(); 128 thd.Join(); // This ensure that the call got un-blocked 129 grpc_core::Fork::GlobalShutdown(); 130 } 131 132 int main(int argc, char* argv[]) { 133 grpc_test_init(argc, argv); 134 test_init(); 135 test_thd_count(); 136 test_exec_count(); 137 138 return 0; 139 } 140