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 <grpc/impl/codegen/gpr_types.h>
22 #include <inttypes.h>
23 #include <signal.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include <grpc/grpc.h>
30 #include <grpc/support/alloc.h>
31 #include <grpc/support/log.h>
32 
33 #include "src/core/lib/gpr/string.h"
34 #include "src/core/lib/gpr/useful.h"
35 #include "src/core/lib/surface/init.h"
36 
37 int64_t g_fixture_slowdown_factor = 1;
38 int64_t g_poller_slowdown_factor = 1;
39 
40 #if GPR_GETPID_IN_UNISTD_H
41 #include <unistd.h>
seed(void)42 static unsigned seed(void) { return static_cast<unsigned>(getpid()); }
43 #endif
44 
45 #if GPR_GETPID_IN_PROCESS_H
46 #include <process.h>
seed(void)47 static unsigned seed(void) { return (unsigned)_getpid(); }
48 #endif
49 
50 #if GPR_WINDOWS_CRASH_HANDLER
51 #include <windows.h>
52 
53 #include <tchar.h>
54 
55 // disable warning 4091 - dbghelp.h is broken for msvc2015
56 #pragma warning(disable : 4091)
57 #define DBGHELP_TRANSLATE_TCHAR
58 #include <dbghelp.h>
59 
60 #ifdef _MSC_VER
61 #pragma comment(lib, "dbghelp.lib")
62 #endif
63 
print_current_stack()64 static void print_current_stack() {
65   typedef USHORT(WINAPI * CaptureStackBackTraceType)(
66       __in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
67   CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(
68       LoadLibrary(_T("kernel32.dll")), "RtlCaptureStackBackTrace"));
69 
70   if (func == NULL) return;  // WOE 29.SEP.2010
71 
72 // Quote from Microsoft Documentation:
73 // ## Windows Server 2003 and Windows XP:
74 // ## The sum of the FramesToSkip and FramesToCapture parameters must be less
75 // than 63.
76 #define MAX_CALLERS 62
77 
78   void* callers_stack[MAX_CALLERS];
79   unsigned short frames;
80   SYMBOL_INFOW* symbol;
81   HANDLE process;
82   process = GetCurrentProcess();
83   SymInitialize(process, NULL, TRUE);
84   frames = (func)(0, MAX_CALLERS, callers_stack, NULL);
85   symbol =
86       (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
87   symbol->MaxNameLen = 255;
88   symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
89 
90   const unsigned short MAX_CALLERS_SHOWN = 32;
91   frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN;
92   for (unsigned int i = 0; i < frames; i++) {
93     SymFromAddrW(process, (DWORD64)(callers_stack[i]), 0, symbol);
94     fwprintf(stderr, L"*** %d: %016I64X %ls - %016I64X\n", i,
95              (DWORD64)callers_stack[i], symbol->Name, (DWORD64)symbol->Address);
96     fflush(stderr);
97   }
98 
99   free(symbol);
100 }
101 
print_stack_from_context(CONTEXT c)102 static void print_stack_from_context(CONTEXT c) {
103   STACKFRAME s;  // in/out stackframe
104   memset(&s, 0, sizeof(s));
105   DWORD imageType;
106 #ifdef _M_IX86
107   // normally, call ImageNtHeader() and use machine info from PE header
108   imageType = IMAGE_FILE_MACHINE_I386;
109   s.AddrPC.Offset = c.Eip;
110   s.AddrPC.Mode = AddrModeFlat;
111   s.AddrFrame.Offset = c.Ebp;
112   s.AddrFrame.Mode = AddrModeFlat;
113   s.AddrStack.Offset = c.Esp;
114   s.AddrStack.Mode = AddrModeFlat;
115 #elif _M_X64
116   imageType = IMAGE_FILE_MACHINE_AMD64;
117   s.AddrPC.Offset = c.Rip;
118   s.AddrPC.Mode = AddrModeFlat;
119   s.AddrFrame.Offset = c.Rbp;
120   s.AddrFrame.Mode = AddrModeFlat;
121   s.AddrStack.Offset = c.Rsp;
122   s.AddrStack.Mode = AddrModeFlat;
123 #elif _M_IA64
124   imageType = IMAGE_FILE_MACHINE_IA64;
125   s.AddrPC.Offset = c.StIIP;
126   s.AddrPC.Mode = AddrModeFlat;
127   s.AddrFrame.Offset = c.IntSp;
128   s.AddrFrame.Mode = AddrModeFlat;
129   s.AddrBStore.Offset = c.RsBSP;
130   s.AddrBStore.Mode = AddrModeFlat;
131   s.AddrStack.Offset = c.IntSp;
132   s.AddrStack.Mode = AddrModeFlat;
133 #else
134 #error "Platform not supported!"
135 #endif
136 
137   HANDLE process = GetCurrentProcess();
138   HANDLE thread = GetCurrentThread();
139 
140   SYMBOL_INFOW* symbol =
141       (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
142   symbol->MaxNameLen = 255;
143   symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
144 
145   while (StackWalk(imageType, process, thread, &s, &c, 0,
146                    SymFunctionTableAccess, SymGetModuleBase, 0)) {
147     BOOL has_symbol =
148         SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol);
149     fwprintf(
150         stderr, L"*** %016I64X %ls - %016I64X\n", (DWORD64)(s.AddrPC.Offset),
151         has_symbol ? symbol->Name : L"<<no symbol>>", (DWORD64)symbol->Address);
152     fflush(stderr);
153   }
154 
155   free(symbol);
156 }
157 
crash_handler(struct _EXCEPTION_POINTERS * ex_info)158 static LONG crash_handler(struct _EXCEPTION_POINTERS* ex_info) {
159   fprintf(stderr, "Exception handler called, dumping information\n");
160   bool try_to_print_stack = true;
161   PEXCEPTION_RECORD exrec = ex_info->ExceptionRecord;
162   while (exrec) {
163     DWORD code = exrec->ExceptionCode;
164     DWORD flgs = exrec->ExceptionFlags;
165     PVOID addr = exrec->ExceptionAddress;
166     if (code == EXCEPTION_STACK_OVERFLOW) try_to_print_stack = false;
167     fprintf(stderr, "code: %x - flags: %d - address: %p\n", code, flgs, addr);
168     exrec = exrec->ExceptionRecord;
169   }
170   if (try_to_print_stack) {
171     print_stack_from_context(*ex_info->ContextRecord);
172   }
173   if (IsDebuggerPresent()) {
174     __debugbreak();
175   } else {
176     _exit(1);
177   }
178   return EXCEPTION_EXECUTE_HANDLER;
179 }
180 
abort_handler(int sig)181 static void abort_handler(int sig) {
182   fprintf(stderr, "Abort handler called.\n");
183   print_current_stack();
184   if (IsDebuggerPresent()) {
185     __debugbreak();
186   } else {
187     _exit(1);
188   }
189 }
190 
install_crash_handler()191 static void install_crash_handler() {
192   if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
193     fprintf(stderr, "SymInitialize failed: %d\n", GetLastError());
194   }
195   SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler);
196   _set_abort_behavior(0, _WRITE_ABORT_MSG);
197   _set_abort_behavior(0, _CALL_REPORTFAULT);
198   signal(SIGABRT, abort_handler);
199 }
200 #elif GPR_POSIX_CRASH_HANDLER
201 #include <errno.h>
202 #include <execinfo.h>
203 #include <stdio.h>
204 #include <string.h>
205 
206 #define SIGNAL_NAMES_LENGTH 32
207 
208 static const char* const signal_names[] = {
209     nullptr,   "SIGHUP",  "SIGINT",    "SIGQUIT", "SIGILL",    "SIGTRAP",
210     "SIGABRT", "SIGBUS",  "SIGFPE",    "SIGKILL", "SIGUSR1",   "SIGSEGV",
211     "SIGUSR2", "SIGPIPE", "SIGALRM",   "SIGTERM", "SIGSTKFLT", "SIGCHLD",
212     "SIGCONT", "SIGSTOP", "SIGTSTP",   "SIGTTIN", "SIGTTOU",   "SIGURG",
213     "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH",  "SIGIO",
214     "SIGPWR",  "SIGSYS"};
215 
216 static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)];
217 
218 #define MAX_FRAMES 32
219 
220 /* signal safe output */
output_string(const char * string)221 static void output_string(const char* string) {
222   size_t len = strlen(string);
223   ssize_t r;
224 
225   do {
226     r = write(STDERR_FILENO, string, len);
227   } while (r == -1 && errno == EINTR);
228 }
229 
output_num(long num)230 static void output_num(long num) {
231   char buf[GPR_LTOA_MIN_BUFSIZE];
232   gpr_ltoa(num, buf);
233   output_string(buf);
234 }
235 
crash_handler(int signum,siginfo_t *,void *)236 static void crash_handler(int signum, siginfo_t* /*info*/, void* /*data*/) {
237   void* addrlist[MAX_FRAMES + 1];
238   int addrlen;
239 
240   output_string("\n\n\n*******************************\nCaught signal ");
241   if (signum > 0 && signum < SIGNAL_NAMES_LENGTH) {
242     output_string(signal_names[signum]);
243   } else {
244     output_num(signum);
245   }
246   output_string("\n");
247 
248   addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist));
249 
250   if (addrlen == 0) {
251     output_string("  no backtrace\n");
252   } else {
253     backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO);
254   }
255 
256   /* try to get a core dump for SIGTERM */
257   if (signum == SIGTERM) signum = SIGQUIT;
258   raise(signum);
259 }
260 
install_crash_handler()261 static void install_crash_handler() {
262   stack_t ss;
263   struct sigaction sa;
264 
265   memset(&ss, 0, sizeof(ss));
266   memset(&sa, 0, sizeof(sa));
267   ss.ss_size = sizeof(g_alt_stack);
268   ss.ss_sp = g_alt_stack;
269   GPR_ASSERT(sigaltstack(&ss, nullptr) == 0);
270   sa.sa_flags = static_cast<int>(SA_SIGINFO | SA_ONSTACK | SA_RESETHAND);
271   sa.sa_sigaction = crash_handler;
272   GPR_ASSERT(sigaction(SIGILL, &sa, nullptr) == 0);
273   GPR_ASSERT(sigaction(SIGABRT, &sa, nullptr) == 0);
274   GPR_ASSERT(sigaction(SIGBUS, &sa, nullptr) == 0);
275   GPR_ASSERT(sigaction(SIGSEGV, &sa, nullptr) == 0);
276   GPR_ASSERT(sigaction(SIGTERM, &sa, nullptr) == 0);
277   GPR_ASSERT(sigaction(SIGQUIT, &sa, nullptr) == 0);
278 }
279 #else
install_crash_handler()280 static void install_crash_handler() {}
281 #endif
282 
BuiltUnderValgrind()283 bool BuiltUnderValgrind() {
284 #ifdef RUNNING_ON_VALGRIND
285   return true;
286 #else
287   return false;
288 #endif
289 }
290 
BuiltUnderTsan()291 bool BuiltUnderTsan() {
292 #if defined(__has_feature)
293 #if __has_feature(thread_sanitizer)
294   return true;
295 #else
296   return false;
297 #endif
298 #else
299 #ifdef THREAD_SANITIZER
300   return true;
301 #else
302   return false;
303 #endif
304 #endif
305 }
306 
BuiltUnderAsan()307 bool BuiltUnderAsan() {
308 #if defined(__has_feature)
309 #if __has_feature(address_sanitizer)
310   return true;
311 #else
312   return false;
313 #endif
314 #else
315 #ifdef ADDRESS_SANITIZER
316   return true;
317 #else
318   return false;
319 #endif
320 #endif
321 }
322 
BuiltUnderMsan()323 bool BuiltUnderMsan() {
324 #if defined(__has_feature)
325 #if __has_feature(memory_sanitizer)
326   return true;
327 #else
328   return false;
329 #endif
330 #else
331 #ifdef MEMORY_SANITIZER
332   return true;
333 #else
334   return false;
335 #endif
336 #endif
337 }
338 
BuiltUnderUbsan()339 bool BuiltUnderUbsan() {
340 #ifdef GRPC_UBSAN
341   return true;
342 #else
343   return false;
344 #endif
345 }
346 
grpc_test_sanitizer_slowdown_factor()347 int64_t grpc_test_sanitizer_slowdown_factor() {
348   int64_t sanitizer_multiplier = 1;
349   if (BuiltUnderValgrind()) {
350     sanitizer_multiplier = 20;
351   } else if (BuiltUnderTsan()) {
352     sanitizer_multiplier = 5;
353   } else if (BuiltUnderAsan()) {
354     sanitizer_multiplier = 3;
355   } else if (BuiltUnderMsan()) {
356     sanitizer_multiplier = 4;
357   } else if (BuiltUnderUbsan()) {
358     sanitizer_multiplier = 5;
359   }
360   return sanitizer_multiplier;
361 }
362 
grpc_test_slowdown_factor()363 int64_t grpc_test_slowdown_factor() {
364   return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor *
365          g_poller_slowdown_factor;
366 }
367 
grpc_timeout_seconds_to_deadline(int64_t time_s)368 gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) {
369   return gpr_time_add(
370       gpr_now(GPR_CLOCK_MONOTONIC),
371       gpr_time_from_millis(
372           grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_s,
373           GPR_TIMESPAN));
374 }
375 
grpc_timeout_milliseconds_to_deadline(int64_t time_ms)376 gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
377   return gpr_time_add(
378       gpr_now(GPR_CLOCK_MONOTONIC),
379       gpr_time_from_micros(
380           grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_ms,
381           GPR_TIMESPAN));
382 }
383 
grpc_test_init(int,char **)384 void grpc_test_init(int /*argc*/, char** /*argv*/) {
385   install_crash_handler();
386   gpr_log(GPR_DEBUG,
387           "test slowdown factor: sanitizer=%" PRId64 ", fixture=%" PRId64
388           ", poller=%" PRId64 ", total=%" PRId64,
389           grpc_test_sanitizer_slowdown_factor(), g_fixture_slowdown_factor,
390           g_poller_slowdown_factor, grpc_test_slowdown_factor());
391   /* seed rng with pid, so we don't end up with the same random numbers as a
392      concurrently running test binary */
393   srand(seed());
394 }
395 
396 namespace grpc {
397 namespace testing {
398 
TestEnvironment(int argc,char ** argv)399 TestEnvironment::TestEnvironment(int argc, char** argv) {
400   grpc_test_init(argc, argv);
401 }
402 
~TestEnvironment()403 TestEnvironment::~TestEnvironment() {
404   // This will wait until gRPC shutdown has actually happened to make sure
405   // no gRPC resources (such as thread) are active. (timeout = 10s)
406   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10);
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_MONOTONIC), deadline) > 0) {
412       gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
413       break;
414     }
415   }
416 }
417 
418 }  // namespace testing
419 }  // namespace grpc
420