Mercurial > projects > doodle
annotate doodle/core/backtrace.d @ 88:100dd23c7bdf
Ch ch ch changes:
* Handle SIGINT like a geek for now
* GtkD Context has no destructor and hence it would seem, a memory leak
* No more gtk_* C-function invocations
* Configured my GtkD patches
* (Comments)
author | David Bryant <bagnose@gmail.com> |
---|---|
date | Wed, 18 Aug 2010 23:51:43 +0930 |
parents | 43cc2135ced0 |
children | 345fb56d89fc ab745d8b10e5 |
rev | line source |
---|---|
44 | 1 module doodle.core.backtrace; |
2 | |
3 // | |
4 // Provides support for a readable backtrace on a program crash. | |
5 // | |
6 // Everything is private - you build this into a library and | |
7 // link to the library, and bingo (via static this). | |
8 // | |
9 // It works by registering a stacktrace handler with the runtime, | |
10 // which, unlike the default one, provides demangled symbols | |
11 // rather than just a list of addresses. | |
12 // | |
13 | |
14 private { | |
15 | |
50
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
16 import core.stdc.signal; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
17 import core.stdc.stdlib : free; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
18 import core.stdc.string : strlen; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
19 import core.runtime; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
20 import std.demangle; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
21 import std.string; |
44 | 22 |
50
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
23 extern (C) int backtrace(void**, size_t); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
24 extern (C) char** backtrace_symbols(void**, int); |
44 | 25 |
26 // signal handler for otherwise-fatal thread-specific signals | |
66 | 27 extern (C) void signalHandler(int sig) { |
44 | 28 string name() { |
29 switch (sig) { | |
30 case SIGSEGV: return "SIGSEGV"; | |
31 case SIGFPE: return "SIGFPE"; | |
32 case SIGILL: return "SIGILL"; | |
33 case SIGABRT: return "SIGABRT"; | |
88 | 34 case SIGINT: return "SIGINT"; |
44 | 35 default: return ""; |
36 } | |
37 } | |
38 | |
39 throw new Error(format("Got signal %s %s", sig, name)); | |
40 } | |
41 | |
42 shared static this() { | |
43 // set up shared signal handlers for fatal thread-specific signals | |
66 | 44 signal(SIGABRT, &signalHandler); |
45 signal(SIGFPE, &signalHandler); | |
46 signal(SIGILL, &signalHandler); | |
47 signal(SIGSEGV, &signalHandler); | |
88 | 48 signal(SIGINT, &signalHandler); |
44 | 49 } |
50 | |
51 static this() { | |
52 // register our trace handler for each thread | |
53 Runtime.traceHandler = &traceHandler; | |
54 } | |
55 | |
56 Throwable.TraceInfo traceHandler(void * ptr = null) { | |
57 return new TraceInfo; | |
58 } | |
50
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
59 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
60 class TraceInfo : Throwable.TraceInfo { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
61 this() { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
62 immutable MAXFRAMES = 128; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
63 void*[MAXFRAMES] callstack; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
64 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
65 numframes = backtrace(callstack.ptr, MAXFRAMES); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
66 framelist = backtrace_symbols(callstack.ptr, numframes); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
67 } |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
68 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
69 ~this() { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
70 free(framelist); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
71 } |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
72 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
73 override string toString() const { return null; } // Why does toString require overriding? |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
74 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
75 override int opApply(scope int delegate(ref char[]) dg) { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
76 // NOTE: The first 5 frames with the current implementation are |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
77 // inside core.runtime and the object code, so eliminate |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
78 // these for readability. |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
79 immutable FIRSTFRAME = 5; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
80 int ret = 0; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
81 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
82 for(int i = FIRSTFRAME; i < numframes; ++i) { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
83 char[] text = framelist[i][0 .. strlen(framelist[i])]; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
84 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
85 int a = text.lastIndexOf('('); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
86 int b = text.lastIndexOf('+'); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
87 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
88 if (a != -1 && b != -1) { |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
89 ++a; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
90 text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
91 } |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
92 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
93 ret = dg(text); |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
94 if (ret) |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
95 break; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
96 } |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
97 return ret; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
98 } |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
99 |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
100 private: |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
101 int numframes; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
102 char** framelist; |
dfa1e219eafe
New version of backtrace based on the one in druntime.
daveb
parents:
45
diff
changeset
|
103 } |
44 | 104 } |