blob: 193e1af0b251a2053482ca3c0c892fde9e027e50 [file] [log] [blame]
mtklein30e6e2a2014-06-18 11:44:15 -07001#include "CrashHandler.h"
2
3#include "SkTypes.h"
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <signal.h>
8
9#if defined(SK_BUILD_FOR_MAC)
10
11// We only use local unwinding, so we can define this to select a faster implementation.
12#define UNW_LOCAL_ONLY
13#include <libunwind.h>
14#include <cxxabi.h>
15
16static void handler(int sig) {
17 unw_context_t context;
18 unw_getcontext(&context);
19
20 unw_cursor_t cursor;
21 unw_init_local(&cursor, &context);
22
23 fprintf(stderr, "\nSignal %d:\n", sig);
24 while (unw_step(&cursor) > 0) {
25 static const size_t kMax = 256;
26 char mangled[kMax], demangled[kMax];
27 unw_word_t offset;
28 unw_get_proc_name(&cursor, mangled, kMax, &offset);
29
30 int ok;
31 size_t len = kMax;
32 abi::__cxa_demangle(mangled, demangled, &len, &ok);
33
34 fprintf(stderr, "%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset);
35 }
36 fprintf(stderr, "\n");
37
38 // Exit NOW. Don't notify other threads, don't call anything registered with atexit().
39 _Exit(sig);
40}
41
42#elif defined(SK_BUILD_FOR_UNIX)
43
44// We'd use libunwind here too, but it's a pain to get installed for both 32 and 64 bit on bots.
45// Doesn't matter much: catchsegv is best anyway.
46#include <execinfo.h>
47
48static void handler(int sig) {
49 static const int kMax = 64;
50 void* stack[kMax];
51 const int count = backtrace(stack, kMax);
52
53 fprintf(stderr, "\nSignal %d:\n", sig);
54 backtrace_symbols_fd(stack, count, 2/*stderr*/);
55
56 // Exit NOW. Don't notify other threads, don't call anything registered with atexit().
57 _Exit(sig);
58}
59
60#endif
61
62#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_MAC)
63
64void SetupCrashHandler() {
65 static const int kSignals[] = {
66 SIGABRT,
67 SIGBUS,
68 SIGFPE,
69 SIGILL,
70 SIGSEGV,
71 };
72
73 for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) {
74 // Register our signal handler unless something's already done so (e.g. catchsegv).
75 void (*prev)(int) = signal(kSignals[i], handler);
76 if (prev != SIG_DFL) {
77 signal(kSignals[i], prev);
78 }
79 }
80}
81
82// TODO: #elif defined(SK_BUILD_FOR_WIN) when I find a Windows machine to work from.
83
84#else
85
86void SetupCrashHandler() { }
87
88#endif