<html><body bgcolor="#FFFFFF"><div></div><div>I just want to ensure this post to digitalmars.D doesn't get lost.</div><div><br></div><div>It looks like a change to dmd.conf (similar to OSX?) and a patch to druntime. Sean replied to the start of the thread, but not this revised post.</div><div><br></div><div><a href="http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&amp;article_id=114487">http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&amp;article_id=114487</a></div><span class="Apple-style-span" style="font-family: Tahoma, sans-serif; -webkit-tap-highlight-color: rgba(26, 26, 26, 0.296875); -webkit-composition-fill-color: rgba(175, 192, 227, 0.230469); -webkit-composition-frame-color: rgba(77, 128, 180, 0.230469); font-size: medium; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><table cellpadding="5" cellspacing="0" border="0" align="left" width="100%"><tbody><tr><td colspan="2"><font size="-1"><br>module backtrace;<br><br>//<br>// Provides support for a readable backtrace on a program crash.<br>//<br>// Everything is private - you build this into a library and<br>// link to the library, and bingo (via static this).<br>//<br>// It works by registering a stacktrace handler with the runtime,<br>// which, unlike the default one, provides demangled symbols<br>// rather than just a list of addresses.<br>//<br><br>private {<br><br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.signal;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.stdlib : free;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.string : strlen;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.runtime;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.demangle;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.string;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) int&nbsp;&nbsp;&nbsp;&nbsp;backtrace(void**, size_t);<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) char** backtrace_symbols(void**, int);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;// signal handler for otherwise-fatal thread-specific signals&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) void signal_handler(int sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string name() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGSEGV: return "SIGSEGV";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGFPE:&nbsp;&nbsp;return "SIGFPE";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGILL:&nbsp;&nbsp;return "SIGILL";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGABRT: return "SIGABRT";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new Error(format("Got signal %s %s", sig, name));<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;shared static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// set up shared signal handlers for fatal thread-specific signals<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGABRT, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGFPE,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGILL,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGSEGV, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// register our trace handler for each thread<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.traceHandler = &amp;traceHandler;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Throwable.TraceInfo traceHandler(void * ptr = null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new TraceInfo;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;class TraceInfo : Throwable.TraceInfo {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable MAXFRAMES = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void*[MAXFRAMES] callstack;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numframes = backtrace(callstack.ptr, MAXFRAMES);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;framelist = backtrace_symbols(callstack.ptr, numframes);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(framelist);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override string toString() const { return null; }&nbsp;&nbsp; // Why does toString require overriding?<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override int opApply(scope int delegate(ref char[]) dg) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// NOTE: The first 5 frames with the current implementation are<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inside core.runtime and the object code, so eliminate<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; these for readability.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable FIRSTFRAME = 5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int ret = 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i = FIRSTFRAME; i &lt; numframes; ++i) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a = text.lastIndexOf('(');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int b = text.lastIndexOf('+');<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (a != -1 &amp;&amp; b != -1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret = dg(text);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (ret)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ret;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;numframes;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char** framelist;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br><br></font></td></tr></tbody></table></span><span class="Apple-style-span" style="font-family: Tahoma, sans-serif; -webkit-tap-highlight-color: rgba(26, 26, 26, 0.296875); -webkit-composition-fill-color: rgba(175, 192, 227, 0.230469); -webkit-composition-frame-color: rgba(77, 128, 180, 0.230469); font-size: medium; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><table cellpadding="5" cellspacing="0" border="0" align="left" width="100%"><tbody><tr><td colspan="2"><font size="-1"><br>Ok,<br><br>I've added -L--export-dynamic to dmd.conf and done a copy/modify of&nbsp;<br>DefaultTraceInfo from runtime.d to include demangling and catch certain&nbsp;<br>signals. My backtraces now look gorgeous under Linux.<br><br>I've attached the source for the updated module.<br><br>Thanks,<br>Dave<br><br>On&nbsp;<a href="tel:04/08/10%2012" style="text-decoration: none; ">04/08/10 12</a>:39, Sean Kelly wrote:<br><i>&gt; Graham St Jack Wrote:<br></i><i>&gt;&gt;<br></i><i>&gt;&gt; Sean, is there any chance of you rolling some of the good stuff in this<br></i><i>&gt;&gt; code into druntime?<br></i><i>&gt;&gt;<br></i><i>&gt;&gt; In particular, it would be very nice to get symbol names in a stacktrace<br></i><i>&gt;&gt; rather than a bunch of addresses, and even nicer to get a stacktrace on<br></i><i>&gt;&gt; a SIGSEGV.<br></i><i>&gt;<br></i><i>&gt; You can get the symbol names by adding -L--export-dynamic to your DFLAGS in dmd.conf.&nbsp;&nbsp;That option is on by default on OSX and I didn't realize it was different on Linux.&nbsp;&nbsp;I'll sort out demangling as well, it's just a bit more work.&nbsp;&nbsp;I like the stack trace code provided, but it uses a lot of modules that aren't available to druntime so it would be difficult to use directly.<br></i><br><br><br></font></td></tr><tr><td colspan="2"><font size="-1"><br>module backtrace;<br><br>//<br>// Provides support for a readable backtrace on a program crash.<br>//<br>// Everything is private - you build this into a library and<br>// link to the library, and bingo (via static this).<br>//<br>// It works by registering a stacktrace handler with the runtime,<br>// which, unlike the default one, provides demangled symbols<br>// rather than just a list of addresses.<br>//<br><br>private {<br><br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.signal;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.stdlib : free;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.string : strlen;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.runtime;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.demangle;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.string;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) int&nbsp;&nbsp;&nbsp;&nbsp;backtrace(void**, size_t);<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) char** backtrace_symbols(void**, int);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;// signal handler for otherwise-fatal thread-specific signals&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) void signal_handler(int sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string name() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGSEGV: return "SIGSEGV";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGFPE:&nbsp;&nbsp;return "SIGFPE";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGILL:&nbsp;&nbsp;return "SIGILL";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGABRT: return "SIGABRT";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new Error(format("Got signal %s %s", sig, name));<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;shared static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// set up shared signal handlers for fatal thread-specific signals<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGABRT, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGFPE,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGILL,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGSEGV, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// register our trace handler for each thread<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.traceHandler = &amp;traceHandler;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Throwable.TraceInfo traceHandler(void * ptr = null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new TraceInfo;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;class TraceInfo : Throwable.TraceInfo {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable MAXFRAMES = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void*[MAXFRAMES] callstack;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numframes = backtrace(callstack.ptr, MAXFRAMES);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;framelist = backtrace_symbols(callstack.ptr, numframes);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(framelist);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override string toString() const { return null; }&nbsp;&nbsp; // Why does toString require overriding?<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override int opApply(scope int delegate(ref char[]) dg) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// NOTE: The first 5 frames with the current implementation are<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inside core.runtime and the object code, so eliminate<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; these for readability.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable FIRSTFRAME = 5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int ret = 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i = FIRSTFRAME; i &lt; numframes; ++i) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a = text.lastIndexOf('(');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int b = text.lastIndexOf('+');<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (a != -1 &amp;&amp; b != -1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret = dg(text);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (ret)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ret;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;numframes;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char** framelist;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br><br></font></td></tr></tbody></table></span><span class="Apple-style-span" style="font-family: Tahoma, sans-serif; -webkit-tap-highlight-color: rgba(26, 26, 26, 0.296875); -webkit-composition-fill-color: rgba(175, 192, 227, 0.230469); -webkit-composition-frame-color: rgba(77, 128, 180, 0.230469); font-size: medium; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><table cellpadding="5" cellspacing="0" border="0" align="left" width="100%"><tbody><tr><td colspan="2"><font size="-1"><br>Ok,<br><br>I've added -L--export-dynamic to dmd.conf and done a copy/modify of&nbsp;<br>DefaultTraceInfo from runtime.d to include demangling and catch certain&nbsp;<br>signals. My backtraces now look gorgeous under Linux.<br><br>I've attached the source for the updated module.<br><br>Thanks,<br>Dave<br><br>On&nbsp;<a href="tel:04/08/10%2012" style="text-decoration: none; ">04/08/10 12</a>:39, Sean Kelly wrote:<br><i>&gt; Graham St Jack Wrote:<br></i><i>&gt;&gt;<br></i><i>&gt;&gt; Sean, is there any chance of you rolling some of the good stuff in this<br></i><i>&gt;&gt; code into druntime?<br></i><i>&gt;&gt;<br></i><i>&gt;&gt; In particular, it would be very nice to get symbol names in a stacktrace<br></i><i>&gt;&gt; rather than a bunch of addresses, and even nicer to get a stacktrace on<br></i><i>&gt;&gt; a SIGSEGV.<br></i><i>&gt;<br></i><i>&gt; You can get the symbol names by adding -L--export-dynamic to your DFLAGS in dmd.conf.&nbsp;&nbsp;That option is on by default on OSX and I didn't realize it was different on Linux.&nbsp;&nbsp;I'll sort out demangling as well, it's just a bit more work.&nbsp;&nbsp;I like the stack trace code provided, but it uses a lot of modules that aren't available to druntime so it would be difficult to use directly.<br></i><br><br><br></font></td></tr><tr><td colspan="2"><font size="-1"><br>module backtrace;<br><br>//<br>// Provides support for a readable backtrace on a program crash.<br>//<br>// Everything is private - you build this into a library and<br>// link to the library, and bingo (via static this).<br>//<br>// It works by registering a stacktrace handler with the runtime,<br>// which, unlike the default one, provides demangled symbols<br>// rather than just a list of addresses.<br>//<br><br>private {<br><br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.signal;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.stdlib : free;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.string : strlen;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.runtime;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.demangle;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.string;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) int&nbsp;&nbsp;&nbsp;&nbsp;backtrace(void**, size_t);<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) char** backtrace_symbols(void**, int);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;// signal handler for otherwise-fatal thread-specific signals&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) void signal_handler(int sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string name() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGSEGV: return "SIGSEGV";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGFPE:&nbsp;&nbsp;return "SIGFPE";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGILL:&nbsp;&nbsp;return "SIGILL";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGABRT: return "SIGABRT";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new Error(format("Got signal %s %s", sig, name));<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;shared static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// set up shared signal handlers for fatal thread-specific signals<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGABRT, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGFPE,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGILL,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGSEGV, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// register our trace handler for each thread<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.traceHandler = &amp;traceHandler;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Throwable.TraceInfo traceHandler(void * ptr = null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new TraceInfo;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;class TraceInfo : Throwable.TraceInfo {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable MAXFRAMES = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void*[MAXFRAMES] callstack;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numframes = backtrace(callstack.ptr, MAXFRAMES);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;framelist = backtrace_symbols(callstack.ptr, numframes);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(framelist);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override string toString() const { return null; }&nbsp;&nbsp; // Why does toString require overriding?<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override int opApply(scope int delegate(ref char[]) dg) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// NOTE: The first 5 frames with the current implementation are<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inside core.runtime and the object code, so eliminate<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; these for readability.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable FIRSTFRAME = 5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int ret = 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i = FIRSTFRAME; i &lt; numframes; ++i) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a = text.lastIndexOf('(');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int b = text.lastIndexOf('+');<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (a != -1 &amp;&amp; b != -1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret = dg(text);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (ret)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ret;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;numframes;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char** framelist;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br><br></font></td></tr></tbody></table></span><div><span class="Apple-style-span" style="font-family: Tahoma, sans-serif; -webkit-tap-highlight-color: rgba(26, 26, 26, 0.296875); -webkit-composition-fill-color: rgba(175, 192, 227, 0.230469); -webkit-composition-frame-color: rgba(77, 128, 180, 0.230469); font-size: medium; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><table cellpadding="5" cellspacing="0" border="0" align="left" width="100%"><tbody><tr><td colspan="2"><font size="-1"><br>Ok,<br><br>I've added -L--export-dynamic to dmd.conf and done a copy/modify of&nbsp;<br>DefaultTraceInfo from runtime.d to include demangling and catch certain&nbsp;<br>signals. My backtraces now look gorgeous under Linux.<br><br>I've attached the source for the updated module.<br><br>Thanks,<br>Dave<br><br>On&nbsp;<a href="tel:04/08/10%2012" style="text-decoration: none; ">04/08/10 12</a>:39, Sean Kelly wrote:<br><i>&gt; Graham St Jack Wrote:<br></i><i>&gt;&gt;<br></i><i>&gt;&gt; Sean, is there any chance of you rolling some of the good stuff in this<br></i><i>&gt;&gt; code into druntime?<br></i><i>&gt;&gt;<br></i><i>&gt;&gt; In particular, it would be very nice to get symbol names in a stacktrace<br></i><i>&gt;&gt; rather than a bunch of addresses, and even nicer to get a stacktrace on<br></i><i>&gt;&gt; a SIGSEGV.<br></i><i>&gt;<br></i><i>&gt; You can get the symbol names by adding -L--export-dynamic to your DFLAGS in dmd.conf.&nbsp;&nbsp;That option is on by default on OSX and I didn't realize it was different on Linux.&nbsp;&nbsp;I'll sort out demangling as well, it's just a bit more work.&nbsp;&nbsp;I like the stack trace code provided, but it uses a lot of modules that aren't available to druntime so it would be difficult to use directly.<br></i><br><br><br></font></td></tr><tr><td colspan="2"><font size="-1"><br>module backtrace;<br><br>//<br>// Provides support for a readable backtrace on a program crash.<br>//<br>// Everything is private - you build this into a library and<br>// link to the library, and bingo (via static this).<br>//<br>// It works by registering a stacktrace handler with the runtime,<br>// which, unlike the default one, provides demangled symbols<br>// rather than just a list of addresses.<br>//<br><br>private {<br><br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.signal;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.stdlib : free;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.stdc.string : strlen;<br>&nbsp;&nbsp;&nbsp;&nbsp;import core.runtime;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.demangle;<br>&nbsp;&nbsp;&nbsp;&nbsp;import std.string;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) int&nbsp;&nbsp;&nbsp;&nbsp;backtrace(void**, size_t);<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) char** backtrace_symbols(void**, int);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;// signal handler for otherwise-fatal thread-specific signals&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;extern (C) void signal_handler(int sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string name() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (sig) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGSEGV: return "SIGSEGV";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGFPE:&nbsp;&nbsp;return "SIGFPE";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGILL:&nbsp;&nbsp;return "SIGILL";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case SIGABRT: return "SIGABRT";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new Error(format("Got signal %s %s", sig, name));<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;shared static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// set up shared signal handlers for fatal thread-specific signals<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGABRT, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGFPE,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGILL,&nbsp;&nbsp;&amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signal(SIGSEGV, &amp;signal_handler);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;static this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// register our trace handler for each thread<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runtime.traceHandler = &amp;traceHandler;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;Throwable.TraceInfo traceHandler(void * ptr = null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new TraceInfo;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;class TraceInfo : Throwable.TraceInfo {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable MAXFRAMES = 128;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void*[MAXFRAMES] callstack;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numframes = backtrace(callstack.ptr, MAXFRAMES);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;framelist = backtrace_symbols(callstack.ptr, numframes);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~this() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(framelist);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override string toString() const { return null; }&nbsp;&nbsp; // Why does toString require overriding?<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;override int opApply(scope int delegate(ref char[]) dg) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// NOTE: The first 5 frames with the current implementation are<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inside core.runtime and the object code, so eliminate<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; these for readability.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;immutable FIRSTFRAME = 5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int ret = 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i = FIRSTFRAME; i &lt; numframes; ++i) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a = text.lastIndexOf('(');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int b = text.lastIndexOf('+');<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (a != -1 &amp;&amp; b != -1) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret = dg(text);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (ret)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ret;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;numframes;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char** framelist;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br><font class="Apple-style-span" face="Helvetica" size="5"><span class="Apple-style-span" style="font-size: 17px; -webkit-tap-highlight-color: rgba(26, 26, 26, 0.300781); -webkit-composition-fill-color: rgba(175, 192, 227, 0.234375); -webkit-composition-frame-color: rgba(77, 128, 180, 0.234375);"><font class="Apple-style-span" face="Tahoma, sans-serif"><span class="Apple-style-span" style="-webkit-tap-highlight-color: rgba(26, 26, 26, 0.292969); font-size: small;"><br></span></font></span></font></font></td></tr></tbody></table></span></div></body></html>