3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "test/core/util/test_config.h"
28 #include <grpc/grpc.h>
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
32 #include "src/core/lib/gpr/string.h"
33 #include "src/core/lib/gpr/useful.h"
34 #include "src/core/lib/surface/init.h"
36 int64_t g_fixture_slowdown_factor = 1;
37 int64_t g_poller_slowdown_factor = 1;
39 #if GPR_GETPID_IN_UNISTD_H
41 static unsigned seed(void) { return static_cast<unsigned>(getpid()); }
44 #if GPR_GETPID_IN_PROCESS_H
46 static unsigned seed(void) { return (unsigned)_getpid(); }
49 #if GPR_WINDOWS_CRASH_HANDLER
54 // disable warning 4091 - dbghelp.h is broken for msvc2015
55 #pragma warning(disable : 4091)
56 #define DBGHELP_TRANSLATE_TCHAR
60 #pragma comment(lib, "dbghelp.lib")
63 static void print_current_stack() {
64 typedef USHORT(WINAPI * CaptureStackBackTraceType)(
65 __in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
66 CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(
67 LoadLibrary(_T("kernel32.dll")), "RtlCaptureStackBackTrace"));
69 if (func == NULL) return; // WOE 29.SEP.2010
71 // Quote from Microsoft Documentation:
72 // ## Windows Server 2003 and Windows XP:
73 // ## The sum of the FramesToSkip and FramesToCapture parameters must be less
75 #define MAX_CALLERS 62
77 void* callers_stack[MAX_CALLERS];
78 unsigned short frames;
81 process = GetCurrentProcess();
82 SymInitialize(process, NULL, TRUE);
83 frames = (func)(0, MAX_CALLERS, callers_stack, NULL);
85 (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
86 symbol->MaxNameLen = 255;
87 symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
89 const unsigned short MAX_CALLERS_SHOWN = 32;
90 frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN;
91 for (unsigned int i = 0; i < frames; i++) {
92 SymFromAddrW(process, (DWORD64)(callers_stack[i]), 0, symbol);
93 fwprintf(stderr, L"*** %d: %016I64X %ls - %016I64X\n", i,
94 (DWORD64)callers_stack[i], symbol->Name, (DWORD64)symbol->Address);
101 static void print_stack_from_context(CONTEXT c) {
102 STACKFRAME s; // in/out stackframe
103 memset(&s, 0, sizeof(s));
106 // normally, call ImageNtHeader() and use machine info from PE header
107 imageType = IMAGE_FILE_MACHINE_I386;
108 s.AddrPC.Offset = c.Eip;
109 s.AddrPC.Mode = AddrModeFlat;
110 s.AddrFrame.Offset = c.Ebp;
111 s.AddrFrame.Mode = AddrModeFlat;
112 s.AddrStack.Offset = c.Esp;
113 s.AddrStack.Mode = AddrModeFlat;
115 imageType = IMAGE_FILE_MACHINE_AMD64;
116 s.AddrPC.Offset = c.Rip;
117 s.AddrPC.Mode = AddrModeFlat;
118 s.AddrFrame.Offset = c.Rbp;
119 s.AddrFrame.Mode = AddrModeFlat;
120 s.AddrStack.Offset = c.Rsp;
121 s.AddrStack.Mode = AddrModeFlat;
123 imageType = IMAGE_FILE_MACHINE_IA64;
124 s.AddrPC.Offset = c.StIIP;
125 s.AddrPC.Mode = AddrModeFlat;
126 s.AddrFrame.Offset = c.IntSp;
127 s.AddrFrame.Mode = AddrModeFlat;
128 s.AddrBStore.Offset = c.RsBSP;
129 s.AddrBStore.Mode = AddrModeFlat;
130 s.AddrStack.Offset = c.IntSp;
131 s.AddrStack.Mode = AddrModeFlat;
133 #error "Platform not supported!"
136 HANDLE process = GetCurrentProcess();
137 HANDLE thread = GetCurrentThread();
139 SYMBOL_INFOW* symbol =
140 (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
141 symbol->MaxNameLen = 255;
142 symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
144 while (StackWalk(imageType, process, thread, &s, &c, 0,
145 SymFunctionTableAccess, SymGetModuleBase, 0)) {
147 SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol);
149 stderr, L"*** %016I64X %ls - %016I64X\n", (DWORD64)(s.AddrPC.Offset),
150 has_symbol ? symbol->Name : L"<<no symbol>>", (DWORD64)symbol->Address);
157 static LONG crash_handler(struct _EXCEPTION_POINTERS* ex_info) {
158 fprintf(stderr, "Exception handler called, dumping information\n");
159 bool try_to_print_stack = true;
160 PEXCEPTION_RECORD exrec = ex_info->ExceptionRecord;
162 DWORD code = exrec->ExceptionCode;
163 DWORD flgs = exrec->ExceptionFlags;
164 PVOID addr = exrec->ExceptionAddress;
165 if (code == EXCEPTION_STACK_OVERFLOW) try_to_print_stack = false;
166 fprintf(stderr, "code: %x - flags: %d - address: %p\n", code, flgs, addr);
167 exrec = exrec->ExceptionRecord;
169 if (try_to_print_stack) {
170 print_stack_from_context(*ex_info->ContextRecord);
172 if (IsDebuggerPresent()) {
177 return EXCEPTION_EXECUTE_HANDLER;
180 static void abort_handler(int sig) {
181 fprintf(stderr, "Abort handler called.\n");
182 print_current_stack();
183 if (IsDebuggerPresent()) {
190 static void install_crash_handler() {
191 if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
192 fprintf(stderr, "SymInitialize failed: %d\n", GetLastError());
194 SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler);
195 _set_abort_behavior(0, _WRITE_ABORT_MSG);
196 _set_abort_behavior(0, _CALL_REPORTFAULT);
197 signal(SIGABRT, abort_handler);
199 #elif GPR_POSIX_CRASH_HANDLER
201 #include <execinfo.h>
205 #define SIGNAL_NAMES_LENGTH 32
207 static const char* const signal_names[] = {
208 nullptr, "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP",
209 "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", "SIGSEGV",
210 "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", "SIGCHLD",
211 "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG",
212 "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO",
215 static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)];
217 #define MAX_FRAMES 32
219 /* signal safe output */
220 static void output_string(const char* string) {
221 size_t len = strlen(string);
225 r = write(STDERR_FILENO, string, len);
226 } while (r == -1 && errno == EINTR);
229 static void output_num(long num) {
230 char buf[GPR_LTOA_MIN_BUFSIZE];
235 static void crash_handler(int signum, siginfo_t* /*info*/, void* /*data*/) {
236 void* addrlist[MAX_FRAMES + 1];
239 output_string("\n\n\n*******************************\nCaught signal ");
240 if (signum > 0 && signum < SIGNAL_NAMES_LENGTH) {
241 output_string(signal_names[signum]);
247 addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist));
250 output_string(" no backtrace\n");
252 backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO);
255 /* try to get a core dump for SIGTERM */
256 if (signum == SIGTERM) signum = SIGQUIT;
260 static void install_crash_handler() {
264 memset(&ss, 0, sizeof(ss));
265 memset(&sa, 0, sizeof(sa));
266 ss.ss_size = sizeof(g_alt_stack);
267 ss.ss_sp = g_alt_stack;
268 GPR_ASSERT(sigaltstack(&ss, nullptr) == 0);
269 sa.sa_flags = static_cast<int>(SA_SIGINFO | SA_ONSTACK | SA_RESETHAND);
270 sa.sa_sigaction = crash_handler;
271 GPR_ASSERT(sigaction(SIGILL, &sa, nullptr) == 0);
272 GPR_ASSERT(sigaction(SIGABRT, &sa, nullptr) == 0);
273 GPR_ASSERT(sigaction(SIGBUS, &sa, nullptr) == 0);
274 GPR_ASSERT(sigaction(SIGSEGV, &sa, nullptr) == 0);
275 GPR_ASSERT(sigaction(SIGTERM, &sa, nullptr) == 0);
276 GPR_ASSERT(sigaction(SIGQUIT, &sa, nullptr) == 0);
279 static void install_crash_handler() {}
282 bool BuiltUnderValgrind() {
283 #ifdef RUNNING_ON_VALGRIND
290 bool BuiltUnderTsan() {
291 #if defined(__has_feature)
292 #if __has_feature(thread_sanitizer)
298 #ifdef THREAD_SANITIZER
306 bool BuiltUnderAsan() {
307 #if defined(__has_feature)
308 #if __has_feature(address_sanitizer)
314 #ifdef ADDRESS_SANITIZER
322 bool BuiltUnderMsan() {
323 #if defined(__has_feature)
324 #if __has_feature(memory_sanitizer)
330 #ifdef MEMORY_SANITIZER
338 bool BuiltUnderUbsan() {
346 int64_t grpc_test_sanitizer_slowdown_factor() {
347 int64_t sanitizer_multiplier = 1;
348 if (BuiltUnderValgrind()) {
349 sanitizer_multiplier = 20;
350 } else if (BuiltUnderTsan()) {
351 sanitizer_multiplier = 5;
352 } else if (BuiltUnderAsan()) {
353 sanitizer_multiplier = 3;
354 } else if (BuiltUnderMsan()) {
355 sanitizer_multiplier = 4;
356 } else if (BuiltUnderUbsan()) {
357 sanitizer_multiplier = 5;
359 return sanitizer_multiplier;
362 int64_t grpc_test_slowdown_factor() {
363 return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor *
364 g_poller_slowdown_factor;
367 gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) {
369 gpr_now(GPR_CLOCK_MONOTONIC),
370 gpr_time_from_millis(
371 grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_s,
375 gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
377 gpr_now(GPR_CLOCK_MONOTONIC),
378 gpr_time_from_micros(
379 grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_ms,
383 void grpc_test_init(int /*argc*/, char** /*argv*/) {
384 install_crash_handler();
386 "test slowdown factor: sanitizer=%" PRId64 ", fixture=%" PRId64
387 ", poller=%" PRId64 ", total=%" PRId64,
388 grpc_test_sanitizer_slowdown_factor(), g_fixture_slowdown_factor,
389 g_poller_slowdown_factor, grpc_test_slowdown_factor());
390 /* seed rng with pid, so we don't end up with the same random numbers as a
391 concurrently running test binary */
398 TestEnvironment::TestEnvironment(int argc, char** argv) {
399 grpc_test_init(argc, argv);
402 TestEnvironment::~TestEnvironment() {
403 // This will wait until gRPC shutdown has actually happened to make sure
404 // no gRPC resources (such as thread) are active. (timeout = 10s)
405 gpr_timespec timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
406 gpr_time_from_seconds(10, GPR_TIMESPAN));
407 while (grpc_is_initialized()) {
408 grpc_maybe_wait_for_async_shutdown();
409 gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
410 gpr_time_from_millis(1, GPR_TIMESPAN)));
411 if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), timeout) > 0) {
412 gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
418 } // namespace testing