Imported Upstream version 1.27.0
[platform/upstream/grpc.git] / test / core / util / test_config.cc
1 /*
2  *
3  * Copyright 2015 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 "test/core/util/test_config.h"
20
21 #include <inttypes.h>
22 #include <signal.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <grpc/grpc.h>
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
31
32 #include "src/core/lib/gpr/string.h"
33 #include "src/core/lib/gpr/useful.h"
34 #include "src/core/lib/surface/init.h"
35
36 int64_t g_fixture_slowdown_factor = 1;
37 int64_t g_poller_slowdown_factor = 1;
38
39 #if GPR_GETPID_IN_UNISTD_H
40 #include <unistd.h>
41 static unsigned seed(void) { return static_cast<unsigned>(getpid()); }
42 #endif
43
44 #if GPR_GETPID_IN_PROCESS_H
45 #include <process.h>
46 static unsigned seed(void) { return (unsigned)_getpid(); }
47 #endif
48
49 #if GPR_WINDOWS_CRASH_HANDLER
50 #include <windows.h>
51
52 #include <tchar.h>
53
54 // disable warning 4091 - dbghelp.h is broken for msvc2015
55 #pragma warning(disable : 4091)
56 #define DBGHELP_TRANSLATE_TCHAR
57 #include <dbghelp.h>
58
59 #ifdef _MSC_VER
60 #pragma comment(lib, "dbghelp.lib")
61 #endif
62
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"));
68
69   if (func == NULL) return;  // WOE 29.SEP.2010
70
71 // Quote from Microsoft Documentation:
72 // ## Windows Server 2003 and Windows XP:
73 // ## The sum of the FramesToSkip and FramesToCapture parameters must be less
74 // than 63.
75 #define MAX_CALLERS 62
76
77   void* callers_stack[MAX_CALLERS];
78   unsigned short frames;
79   SYMBOL_INFOW* symbol;
80   HANDLE process;
81   process = GetCurrentProcess();
82   SymInitialize(process, NULL, TRUE);
83   frames = (func)(0, MAX_CALLERS, callers_stack, NULL);
84   symbol =
85       (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
86   symbol->MaxNameLen = 255;
87   symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
88
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);
95     fflush(stderr);
96   }
97
98   free(symbol);
99 }
100
101 static void print_stack_from_context(CONTEXT c) {
102   STACKFRAME s;  // in/out stackframe
103   memset(&s, 0, sizeof(s));
104   DWORD imageType;
105 #ifdef _M_IX86
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;
114 #elif _M_X64
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;
122 #elif _M_IA64
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;
132 #else
133 #error "Platform not supported!"
134 #endif
135
136   HANDLE process = GetCurrentProcess();
137   HANDLE thread = GetCurrentThread();
138
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);
143
144   while (StackWalk(imageType, process, thread, &s, &c, 0,
145                    SymFunctionTableAccess, SymGetModuleBase, 0)) {
146     BOOL has_symbol =
147         SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol);
148     fwprintf(
149         stderr, L"*** %016I64X %ls - %016I64X\n", (DWORD64)(s.AddrPC.Offset),
150         has_symbol ? symbol->Name : L"<<no symbol>>", (DWORD64)symbol->Address);
151     fflush(stderr);
152   }
153
154   free(symbol);
155 }
156
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;
161   while (exrec) {
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;
168   }
169   if (try_to_print_stack) {
170     print_stack_from_context(*ex_info->ContextRecord);
171   }
172   if (IsDebuggerPresent()) {
173     __debugbreak();
174   } else {
175     _exit(1);
176   }
177   return EXCEPTION_EXECUTE_HANDLER;
178 }
179
180 static void abort_handler(int sig) {
181   fprintf(stderr, "Abort handler called.\n");
182   print_current_stack();
183   if (IsDebuggerPresent()) {
184     __debugbreak();
185   } else {
186     _exit(1);
187   }
188 }
189
190 static void install_crash_handler() {
191   if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
192     fprintf(stderr, "SymInitialize failed: %d\n", GetLastError());
193   }
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);
198 }
199 #elif GPR_POSIX_CRASH_HANDLER
200 #include <errno.h>
201 #include <execinfo.h>
202 #include <stdio.h>
203 #include <string.h>
204
205 #define SIGNAL_NAMES_LENGTH 32
206
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",
213     "SIGPWR",  "SIGSYS"};
214
215 static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)];
216
217 #define MAX_FRAMES 32
218
219 /* signal safe output */
220 static void output_string(const char* string) {
221   size_t len = strlen(string);
222   ssize_t r;
223
224   do {
225     r = write(STDERR_FILENO, string, len);
226   } while (r == -1 && errno == EINTR);
227 }
228
229 static void output_num(long num) {
230   char buf[GPR_LTOA_MIN_BUFSIZE];
231   gpr_ltoa(num, buf);
232   output_string(buf);
233 }
234
235 static void crash_handler(int signum, siginfo_t* /*info*/, void* /*data*/) {
236   void* addrlist[MAX_FRAMES + 1];
237   int addrlen;
238
239   output_string("\n\n\n*******************************\nCaught signal ");
240   if (signum > 0 && signum < SIGNAL_NAMES_LENGTH) {
241     output_string(signal_names[signum]);
242   } else {
243     output_num(signum);
244   }
245   output_string("\n");
246
247   addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist));
248
249   if (addrlen == 0) {
250     output_string("  no backtrace\n");
251   } else {
252     backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO);
253   }
254
255   /* try to get a core dump for SIGTERM */
256   if (signum == SIGTERM) signum = SIGQUIT;
257   raise(signum);
258 }
259
260 static void install_crash_handler() {
261   stack_t ss;
262   struct sigaction sa;
263
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);
277 }
278 #else
279 static void install_crash_handler() {}
280 #endif
281
282 bool BuiltUnderValgrind() {
283 #ifdef RUNNING_ON_VALGRIND
284   return true;
285 #else
286   return false;
287 #endif
288 }
289
290 bool BuiltUnderTsan() {
291 #if defined(__has_feature)
292 #if __has_feature(thread_sanitizer)
293   return true;
294 #else
295   return false;
296 #endif
297 #else
298 #ifdef THREAD_SANITIZER
299   return true;
300 #else
301   return false;
302 #endif
303 #endif
304 }
305
306 bool BuiltUnderAsan() {
307 #if defined(__has_feature)
308 #if __has_feature(address_sanitizer)
309   return true;
310 #else
311   return false;
312 #endif
313 #else
314 #ifdef ADDRESS_SANITIZER
315   return true;
316 #else
317   return false;
318 #endif
319 #endif
320 }
321
322 bool BuiltUnderMsan() {
323 #if defined(__has_feature)
324 #if __has_feature(memory_sanitizer)
325   return true;
326 #else
327   return false;
328 #endif
329 #else
330 #ifdef MEMORY_SANITIZER
331   return true;
332 #else
333   return false;
334 #endif
335 #endif
336 }
337
338 bool BuiltUnderUbsan() {
339 #ifdef GRPC_UBSAN
340   return true;
341 #else
342   return false;
343 #endif
344 }
345
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;
358   }
359   return sanitizer_multiplier;
360 }
361
362 int64_t grpc_test_slowdown_factor() {
363   return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor *
364          g_poller_slowdown_factor;
365 }
366
367 gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) {
368   return gpr_time_add(
369       gpr_now(GPR_CLOCK_MONOTONIC),
370       gpr_time_from_millis(
371           grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_s,
372           GPR_TIMESPAN));
373 }
374
375 gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
376   return gpr_time_add(
377       gpr_now(GPR_CLOCK_MONOTONIC),
378       gpr_time_from_micros(
379           grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_ms,
380           GPR_TIMESPAN));
381 }
382
383 void grpc_test_init(int /*argc*/, char** /*argv*/) {
384   install_crash_handler();
385   gpr_log(GPR_DEBUG,
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 */
392   srand(seed());
393 }
394
395 namespace grpc {
396 namespace testing {
397
398 TestEnvironment::TestEnvironment(int argc, char** argv) {
399   grpc_test_init(argc, argv);
400 }
401
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");
413       break;
414     }
415   }
416 }
417
418 }  // namespace testing
419 }  // namespace grpc