blob: ede9118ac579cb85b3dfbb4cbe0e73f69865b14a [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller3c788052016-03-16 10:45:32 -07003 * Copyright 2015-2016, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "test/core/util/test_config.h"
35
Nicolas "Pixel" Noble80d68c02015-01-13 20:14:43 -080036#include <grpc/support/port_platform.h>
Craig Tiller8451e872015-02-27 09:25:51 -080037#include <grpc/support/log.h>
Craig Tiller4e710f52015-09-30 07:38:49 -070038#include "src/core/support/string.h"
ctillerb3e33172015-01-05 14:40:53 -080039#include <stdlib.h>
Craig Tillere1e24752015-01-13 17:26:27 -080040#include <signal.h>
Craig Tillerce2b3082016-03-16 10:43:49 -070041#include <stdio.h>
42#include <stdbool.h>
Nicolas "Pixel" Noble80d68c02015-01-13 20:14:43 -080043
Craig Tiller7b9ed352015-08-04 08:55:12 -070044double g_fixture_slowdown_factor = 1.0;
45
Nicolas "Pixel" Noble80d68c02015-01-13 20:14:43 -080046#if GPR_GETPID_IN_UNISTD_H
ctillerb3e33172015-01-05 14:40:53 -080047#include <unistd.h>
Craig Tillera82950e2015-09-22 12:33:20 -070048static unsigned seed(void) { return (unsigned)getpid(); }
Nicolas "Pixel" Noble80d68c02015-01-13 20:14:43 -080049#endif
50
51#if GPR_GETPID_IN_PROCESS_H
52#include <process.h>
Craig Tillera82950e2015-09-22 12:33:20 -070053static unsigned seed(void) { return _getpid(); }
Nicolas "Pixel" Noble80d68c02015-01-13 20:14:43 -080054#endif
ctillerb3e33172015-01-05 14:40:53 -080055
Nicolas "Pixel" Noble717ea0e2015-07-11 22:50:09 +020056#if GPR_WINDOWS_CRASH_HANDLER
Craig Tillerc9c0b8b2016-03-16 14:57:29 -070057#include <windows.h>
58#include <tchar.h>
59#define DBGHELP_TRANSLATE_TCHAR
60#include <dbghelp.h>
Craig Tillerce2b3082016-03-16 10:43:49 -070061
Craig Tillerc9c0b8b2016-03-16 14:57:29 -070062#ifdef _MSC_VER
Craig Tillerce2b3082016-03-16 10:43:49 -070063#pragma comment(lib, "dbghelp.lib")
Craig Tillerc9c0b8b2016-03-16 14:57:29 -070064#endif
Craig Tillerce2b3082016-03-16 10:43:49 -070065
66static void print_current_stack() {
Craig Tiller2b45cb82016-03-16 10:44:57 -070067 typedef USHORT(WINAPI * CaptureStackBackTraceType)(
68 __in ULONG, __in ULONG, __out PVOID *, __out_opt PULONG);
69 CaptureStackBackTraceType func = (CaptureStackBackTraceType)(
Craig Tillerc9c0b8b2016-03-16 14:57:29 -070070 GetProcAddress(LoadLibrary(_T("kernel32.dll")), "RtlCaptureStackBackTrace"));
Craig Tillerce2b3082016-03-16 10:43:49 -070071
Craig Tiller2b45cb82016-03-16 10:44:57 -070072 if (func == NULL) return; // WOE 29.SEP.2010
Craig Tillerce2b3082016-03-16 10:43:49 -070073
Craig Tiller2b45cb82016-03-16 10:44:57 -070074// Quote from Microsoft Documentation:
75// ## Windows Server 2003 and Windows XP:
76// ## The sum of the FramesToSkip and FramesToCapture parameters must be less
77// than 63.
Craig Tillerce2b3082016-03-16 10:43:49 -070078#define MAX_CALLERS 62
79
Craig Tiller2b45cb82016-03-16 10:44:57 -070080 void *callers_stack[MAX_CALLERS];
Craig Tillerce2b3082016-03-16 10:43:49 -070081 unsigned short frames;
Craig Tiller2b45cb82016-03-16 10:44:57 -070082 SYMBOL_INFOW *symbol;
83 HANDLE process;
Craig Tillerce2b3082016-03-16 10:43:49 -070084 process = GetCurrentProcess();
85 SymInitialize(process, NULL, TRUE);
86 frames = (func)(0, MAX_CALLERS, callers_stack, NULL);
Craig Tillerc9c0b8b2016-03-16 14:57:29 -070087 symbol = (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
Craig Tillerce2b3082016-03-16 10:43:49 -070088 symbol->MaxNameLen = 255;
89 symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
90
Craig Tiller2b45cb82016-03-16 10:44:57 -070091 const unsigned short MAX_CALLERS_SHOWN = 32;
Craig Tillerce2b3082016-03-16 10:43:49 -070092 frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN;
93 for (unsigned int i = 0; i < frames; i++) {
94 SymFromAddrW(process, (DWORD64)(callers_stack[i]), 0, symbol);
Craig Tiller2b45cb82016-03-16 10:44:57 -070095 fwprintf(stderr, L"*** %d: %016I64LX %ls - 0x%0X\n", i,
96 (DWORD64)callers_stack[i], symbol->Name, symbol->Address);
Craig Tillerce2b3082016-03-16 10:43:49 -070097 }
98
99 free(symbol);
100}
101
102static void print_stack_from_context(CONTEXT c) {
Craig Tiller2b45cb82016-03-16 10:44:57 -0700103 STACKFRAME s; // in/out stackframe
Craig Tillerce2b3082016-03-16 10:43:49 -0700104 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.Rsp;
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
Craig Tiller2b45cb82016-03-16 10:44:57 -0700140 SYMBOL_INFOW *symbol =
Craig Tillerc9c0b8b2016-03-16 14:57:29 -0700141 (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
Craig Tillerce2b3082016-03-16 10:43:49 -0700142 symbol->MaxNameLen = 255;
143 symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
144
Craig Tiller2b45cb82016-03-16 10:44:57 -0700145 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(stderr, L"*** %016I64LX %ls - 0x%0X\n", (DWORD64)(s.AddrPC.Offset),
150 has_symbol ? symbol->Name : L"<<no symbol>>", symbol->Address);
Craig Tillerce2b3082016-03-16 10:43:49 -0700151 }
152
153 free(symbol);
154}
155
156static LONG crash_handler(struct _EXCEPTION_POINTERS *ex_info) {
157 fprintf(stderr, "Exception handler called, dumping information\n");
158 bool try_to_print_stack = true;
159 PEXCEPTION_RECORD exrec = ex_info->ExceptionRecord;
160 while (exrec) {
161 DWORD code = exrec->ExceptionCode;
162 DWORD flgs = exrec->ExceptionFlags;
163 PVOID addr = exrec->ExceptionAddress;
164 if (code == EXCEPTION_STACK_OVERFLOW) try_to_print_stack = false;
165 fprintf(stderr, "code: %x - flags: %d - address: %p\n", code, flgs, addr);
166 exrec = exrec->ExceptionRecord;
167 }
168 if (try_to_print_stack) {
169 print_stack_from_context(*ex_info->ContextRecord);
Craig Tillera82950e2015-09-22 12:33:20 -0700170 }
171 if (IsDebuggerPresent()) {
172 __debugbreak();
173 } else {
174 _exit(1);
175 }
Nicolas "Pixel" Noble717ea0e2015-07-11 22:50:09 +0200176 return EXCEPTION_EXECUTE_HANDLER;
177}
178
Craig Tillerce2b3082016-03-16 10:43:49 -0700179static void abort_handler(int sig) {
180 fprintf(stderr, "Abort handler called.");
181 print_current_stack(NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700182 if (IsDebuggerPresent()) {
183 __debugbreak();
184 } else {
185 _exit(1);
186 }
Nicolas "Pixel" Noblee1d95d62015-07-14 02:08:50 +0200187}
188
Craig Tillera82950e2015-09-22 12:33:20 -0700189static void install_crash_handler() {
Craig Tillerce2b3082016-03-16 10:43:49 -0700190 if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
191 fprintf(stderr, "SymInitialize failed: %d", GetLastError());
192 }
Craig Tillera82950e2015-09-22 12:33:20 -0700193 SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler);
194 _set_abort_behavior(0, _WRITE_ABORT_MSG);
195 _set_abort_behavior(0, _CALL_REPORTFAULT);
196 signal(SIGABRT, abort_handler);
Nicolas "Pixel" Noble717ea0e2015-07-11 22:50:09 +0200197}
Craig Tiller2bc37292015-09-28 10:08:21 -0700198#elif GPR_POSIX_CRASH_HANDLER
199#include <execinfo.h>
200#include <stdio.h>
201#include <string.h>
202#include <grpc/support/useful.h>
Craig Tiller4e710f52015-09-30 07:38:49 -0700203#include <errno.h>
Craig Tiller2bc37292015-09-28 10:08:21 -0700204
Craig Tiller73c4e872015-09-28 13:21:54 -0700205static char g_alt_stack[MINSIGSTKSZ];
Craig Tiller2bc37292015-09-28 10:08:21 -0700206
207#define MAX_FRAMES 32
208
Craig Tiller4e710f52015-09-30 07:38:49 -0700209/* signal safe output */
210static void output_string(const char *string) {
211 size_t len = strlen(string);
212 ssize_t r;
213
214 do {
215 r = write(STDERR_FILENO, string, len);
216 } while (r == -1 && errno == EINTR);
217}
218
219static void output_num(long num) {
220 char buf[GPR_LTOA_MIN_BUFSIZE];
221 gpr_ltoa(num, buf);
222 output_string(buf);
223}
224
Craig Tiller2bc37292015-09-28 10:08:21 -0700225static void crash_handler(int signum, siginfo_t *info, void *data) {
226 void *addrlist[MAX_FRAMES + 1];
227 int addrlen;
Craig Tiller2bc37292015-09-28 10:08:21 -0700228
Craig Tiller4e710f52015-09-30 07:38:49 -0700229 output_string("\n\n\n*******************************\nCaught signal ");
230 output_num(signum);
231 output_string("\n");
232
Craig Tiller2bc37292015-09-28 10:08:21 -0700233 addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist));
234
Craig Tiller3a12dcf2015-09-30 07:47:08 -0700235 if (addrlen == 0) {
236 output_string(" no backtrace\n");
237 } else {
Craig Tiller2c0b91d2015-09-30 07:49:59 -0700238 backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO);
Craig Tiller2bc37292015-09-28 10:08:21 -0700239 }
Craig Tiller2bc37292015-09-28 10:08:21 -0700240
Craig Tiller4bf29282015-12-14 11:25:48 -0800241 /* try to get a core dump for SIGTERM */
242 if (signum == SIGTERM) signum = SIGQUIT;
Craig Tiller2bc37292015-09-28 10:08:21 -0700243 raise(signum);
244}
245
246static void install_crash_handler() {
247 stack_t ss;
248 struct sigaction sa;
Craig Tiller4e710f52015-09-30 07:38:49 -0700249
Craig Tiller2bc37292015-09-28 10:08:21 -0700250 memset(&ss, 0, sizeof(ss));
251 memset(&sa, 0, sizeof(sa));
252 ss.ss_size = sizeof(g_alt_stack);
253 ss.ss_sp = g_alt_stack;
254 GPR_ASSERT(sigaltstack(&ss, NULL) == 0);
255 sa.sa_flags = (int)(SA_SIGINFO | SA_ONSTACK | SA_RESETHAND);
256 sa.sa_sigaction = crash_handler;
257 GPR_ASSERT(sigaction(SIGILL, &sa, NULL) == 0);
258 GPR_ASSERT(sigaction(SIGABRT, &sa, NULL) == 0);
259 GPR_ASSERT(sigaction(SIGBUS, &sa, NULL) == 0);
260 GPR_ASSERT(sigaction(SIGSEGV, &sa, NULL) == 0);
Craig Tiller4bf29282015-12-14 11:25:48 -0800261 GPR_ASSERT(sigaction(SIGTERM, &sa, NULL) == 0);
262 GPR_ASSERT(sigaction(SIGQUIT, &sa, NULL) == 0);
Craig Tiller2bc37292015-09-28 10:08:21 -0700263}
Nicolas "Pixel" Noble717ea0e2015-07-11 22:50:09 +0200264#else
Craig Tillera82950e2015-09-22 12:33:20 -0700265static void install_crash_handler() {}
Nicolas "Pixel" Noble717ea0e2015-07-11 22:50:09 +0200266#endif
267
Craig Tillera82950e2015-09-22 12:33:20 -0700268void grpc_test_init(int argc, char **argv) {
269 install_crash_handler();
270 gpr_log(GPR_DEBUG, "test slowdown: machine=%f build=%f total=%f",
271 (double)GRPC_TEST_SLOWDOWN_MACHINE_FACTOR,
272 (double)GRPC_TEST_SLOWDOWN_BUILD_FACTOR,
273 (double)GRPC_TEST_SLOWDOWN_FACTOR);
ctillerb3e33172015-01-05 14:40:53 -0800274 /* seed rng with pid, so we don't end up with the same random numbers as a
275 concurrently running test binary */
Craig Tillera82950e2015-09-22 12:33:20 -0700276 srand(seed());
Craig Tiller190d3602015-02-18 09:23:38 -0800277}