<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&article_id=114487">http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&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> import core.stdc.signal;<br> import core.stdc.stdlib : free;<br> import core.stdc.string : strlen;<br> import core.runtime;<br> import std.demangle;<br> import std.string;<br><br> extern (C) int backtrace(void**, size_t);<br> extern (C) char** backtrace_symbols(void**, int);<br><br> // signal handler for otherwise-fatal thread-specific signals <br> extern (C) void signal_handler(int sig) {<br> string name() {<br> switch (sig) {<br> case SIGSEGV: return "SIGSEGV";<br> case SIGFPE: return "SIGFPE";<br> case SIGILL: return "SIGILL";<br> case SIGABRT: return "SIGABRT";<br> default: return "";<br> }<br> }<br><br> throw new Error(format("Got signal %s %s", sig, name));<br> }<br><br> shared static this() {<br> // set up shared signal handlers for fatal thread-specific signals<br> signal(SIGABRT, &signal_handler);<br> signal(SIGFPE, &signal_handler);<br> signal(SIGILL, &signal_handler);<br> signal(SIGSEGV, &signal_handler);<br> }<br><br> static this() {<br> // register our trace handler for each thread<br> Runtime.traceHandler = &traceHandler;<br> }<br><br> Throwable.TraceInfo traceHandler(void * ptr = null) {<br> return new TraceInfo;<br> }<br><br> class TraceInfo : Throwable.TraceInfo {<br> this() {<br> immutable MAXFRAMES = 128;<br> void*[MAXFRAMES] callstack;<br><br> numframes = backtrace(callstack.ptr, MAXFRAMES);<br> framelist = backtrace_symbols(callstack.ptr, numframes);<br> }<br><br> ~this() {<br> free(framelist);<br> }<br><br> override string toString() const { return null; } // Why does toString require overriding?<br><br> override int opApply(scope int delegate(ref char[]) dg) {<br> // NOTE: The first 5 frames with the current implementation are<br> // inside core.runtime and the object code, so eliminate<br> // these for readability.<br> immutable FIRSTFRAME = 5;<br> int ret = 0;<br><br> for(int i = FIRSTFRAME; i < numframes; ++i) {<br> char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br> int a = text.lastIndexOf('(');<br> int b = text.lastIndexOf('+');<br><br> if (a != -1 && b != -1) {<br> ++a;<br> text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br> }<br><br> ret = dg(text);<br> if (ret)<br> break;<br> }<br> return ret;<br> }<br><br> private:<br> int numframes; <br> char** framelist;<br> }<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 <br>DefaultTraceInfo from runtime.d to include demangling and catch certain <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 <a href="tel:04/08/10%2012" style="text-decoration: none; ">04/08/10 12</a>:39, Sean Kelly wrote:<br><i>> Graham St Jack Wrote:<br></i><i>>><br></i><i>>> Sean, is there any chance of you rolling some of the good stuff in this<br></i><i>>> code into druntime?<br></i><i>>><br></i><i>>> In particular, it would be very nice to get symbol names in a stacktrace<br></i><i>>> rather than a bunch of addresses, and even nicer to get a stacktrace on<br></i><i>>> a SIGSEGV.<br></i><i>><br></i><i>> You can get the symbol names by adding -L--export-dynamic to your DFLAGS in dmd.conf. That option is on by default on OSX and I didn't realize it was different on Linux. I'll sort out demangling as well, it's just a bit more work. 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> import core.stdc.signal;<br> import core.stdc.stdlib : free;<br> import core.stdc.string : strlen;<br> import core.runtime;<br> import std.demangle;<br> import std.string;<br><br> extern (C) int backtrace(void**, size_t);<br> extern (C) char** backtrace_symbols(void**, int);<br><br> // signal handler for otherwise-fatal thread-specific signals <br> extern (C) void signal_handler(int sig) {<br> string name() {<br> switch (sig) {<br> case SIGSEGV: return "SIGSEGV";<br> case SIGFPE: return "SIGFPE";<br> case SIGILL: return "SIGILL";<br> case SIGABRT: return "SIGABRT";<br> default: return "";<br> }<br> }<br><br> throw new Error(format("Got signal %s %s", sig, name));<br> }<br><br> shared static this() {<br> // set up shared signal handlers for fatal thread-specific signals<br> signal(SIGABRT, &signal_handler);<br> signal(SIGFPE, &signal_handler);<br> signal(SIGILL, &signal_handler);<br> signal(SIGSEGV, &signal_handler);<br> }<br><br> static this() {<br> // register our trace handler for each thread<br> Runtime.traceHandler = &traceHandler;<br> }<br><br> Throwable.TraceInfo traceHandler(void * ptr = null) {<br> return new TraceInfo;<br> }<br><br> class TraceInfo : Throwable.TraceInfo {<br> this() {<br> immutable MAXFRAMES = 128;<br> void*[MAXFRAMES] callstack;<br><br> numframes = backtrace(callstack.ptr, MAXFRAMES);<br> framelist = backtrace_symbols(callstack.ptr, numframes);<br> }<br><br> ~this() {<br> free(framelist);<br> }<br><br> override string toString() const { return null; } // Why does toString require overriding?<br><br> override int opApply(scope int delegate(ref char[]) dg) {<br> // NOTE: The first 5 frames with the current implementation are<br> // inside core.runtime and the object code, so eliminate<br> // these for readability.<br> immutable FIRSTFRAME = 5;<br> int ret = 0;<br><br> for(int i = FIRSTFRAME; i < numframes; ++i) {<br> char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br> int a = text.lastIndexOf('(');<br> int b = text.lastIndexOf('+');<br><br> if (a != -1 && b != -1) {<br> ++a;<br> text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br> }<br><br> ret = dg(text);<br> if (ret)<br> break;<br> }<br> return ret;<br> }<br><br> private:<br> int numframes; <br> char** framelist;<br> }<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 <br>DefaultTraceInfo from runtime.d to include demangling and catch certain <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 <a href="tel:04/08/10%2012" style="text-decoration: none; ">04/08/10 12</a>:39, Sean Kelly wrote:<br><i>> Graham St Jack Wrote:<br></i><i>>><br></i><i>>> Sean, is there any chance of you rolling some of the good stuff in this<br></i><i>>> code into druntime?<br></i><i>>><br></i><i>>> In particular, it would be very nice to get symbol names in a stacktrace<br></i><i>>> rather than a bunch of addresses, and even nicer to get a stacktrace on<br></i><i>>> a SIGSEGV.<br></i><i>><br></i><i>> You can get the symbol names by adding -L--export-dynamic to your DFLAGS in dmd.conf. That option is on by default on OSX and I didn't realize it was different on Linux. I'll sort out demangling as well, it's just a bit more work. 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> import core.stdc.signal;<br> import core.stdc.stdlib : free;<br> import core.stdc.string : strlen;<br> import core.runtime;<br> import std.demangle;<br> import std.string;<br><br> extern (C) int backtrace(void**, size_t);<br> extern (C) char** backtrace_symbols(void**, int);<br><br> // signal handler for otherwise-fatal thread-specific signals <br> extern (C) void signal_handler(int sig) {<br> string name() {<br> switch (sig) {<br> case SIGSEGV: return "SIGSEGV";<br> case SIGFPE: return "SIGFPE";<br> case SIGILL: return "SIGILL";<br> case SIGABRT: return "SIGABRT";<br> default: return "";<br> }<br> }<br><br> throw new Error(format("Got signal %s %s", sig, name));<br> }<br><br> shared static this() {<br> // set up shared signal handlers for fatal thread-specific signals<br> signal(SIGABRT, &signal_handler);<br> signal(SIGFPE, &signal_handler);<br> signal(SIGILL, &signal_handler);<br> signal(SIGSEGV, &signal_handler);<br> }<br><br> static this() {<br> // register our trace handler for each thread<br> Runtime.traceHandler = &traceHandler;<br> }<br><br> Throwable.TraceInfo traceHandler(void * ptr = null) {<br> return new TraceInfo;<br> }<br><br> class TraceInfo : Throwable.TraceInfo {<br> this() {<br> immutable MAXFRAMES = 128;<br> void*[MAXFRAMES] callstack;<br><br> numframes = backtrace(callstack.ptr, MAXFRAMES);<br> framelist = backtrace_symbols(callstack.ptr, numframes);<br> }<br><br> ~this() {<br> free(framelist);<br> }<br><br> override string toString() const { return null; } // Why does toString require overriding?<br><br> override int opApply(scope int delegate(ref char[]) dg) {<br> // NOTE: The first 5 frames with the current implementation are<br> // inside core.runtime and the object code, so eliminate<br> // these for readability.<br> immutable FIRSTFRAME = 5;<br> int ret = 0;<br><br> for(int i = FIRSTFRAME; i < numframes; ++i) {<br> char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br> int a = text.lastIndexOf('(');<br> int b = text.lastIndexOf('+');<br><br> if (a != -1 && b != -1) {<br> ++a;<br> text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br> }<br><br> ret = dg(text);<br> if (ret)<br> break;<br> }<br> return ret;<br> }<br><br> private:<br> int numframes; <br> char** framelist;<br> }<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 <br>DefaultTraceInfo from runtime.d to include demangling and catch certain <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 <a href="tel:04/08/10%2012" style="text-decoration: none; ">04/08/10 12</a>:39, Sean Kelly wrote:<br><i>> Graham St Jack Wrote:<br></i><i>>><br></i><i>>> Sean, is there any chance of you rolling some of the good stuff in this<br></i><i>>> code into druntime?<br></i><i>>><br></i><i>>> In particular, it would be very nice to get symbol names in a stacktrace<br></i><i>>> rather than a bunch of addresses, and even nicer to get a stacktrace on<br></i><i>>> a SIGSEGV.<br></i><i>><br></i><i>> You can get the symbol names by adding -L--export-dynamic to your DFLAGS in dmd.conf. That option is on by default on OSX and I didn't realize it was different on Linux. I'll sort out demangling as well, it's just a bit more work. 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> import core.stdc.signal;<br> import core.stdc.stdlib : free;<br> import core.stdc.string : strlen;<br> import core.runtime;<br> import std.demangle;<br> import std.string;<br><br> extern (C) int backtrace(void**, size_t);<br> extern (C) char** backtrace_symbols(void**, int);<br><br> // signal handler for otherwise-fatal thread-specific signals <br> extern (C) void signal_handler(int sig) {<br> string name() {<br> switch (sig) {<br> case SIGSEGV: return "SIGSEGV";<br> case SIGFPE: return "SIGFPE";<br> case SIGILL: return "SIGILL";<br> case SIGABRT: return "SIGABRT";<br> default: return "";<br> }<br> }<br><br> throw new Error(format("Got signal %s %s", sig, name));<br> }<br><br> shared static this() {<br> // set up shared signal handlers for fatal thread-specific signals<br> signal(SIGABRT, &signal_handler);<br> signal(SIGFPE, &signal_handler);<br> signal(SIGILL, &signal_handler);<br> signal(SIGSEGV, &signal_handler);<br> }<br><br> static this() {<br> // register our trace handler for each thread<br> Runtime.traceHandler = &traceHandler;<br> }<br><br> Throwable.TraceInfo traceHandler(void * ptr = null) {<br> return new TraceInfo;<br> }<br><br> class TraceInfo : Throwable.TraceInfo {<br> this() {<br> immutable MAXFRAMES = 128;<br> void*[MAXFRAMES] callstack;<br><br> numframes = backtrace(callstack.ptr, MAXFRAMES);<br> framelist = backtrace_symbols(callstack.ptr, numframes);<br> }<br><br> ~this() {<br> free(framelist);<br> }<br><br> override string toString() const { return null; } // Why does toString require overriding?<br><br> override int opApply(scope int delegate(ref char[]) dg) {<br> // NOTE: The first 5 frames with the current implementation are<br> // inside core.runtime and the object code, so eliminate<br> // these for readability.<br> immutable FIRSTFRAME = 5;<br> int ret = 0;<br><br> for(int i = FIRSTFRAME; i < numframes; ++i) {<br> char[] text = framelist[i][0 .. strlen(framelist[i])];<br><br> int a = text.lastIndexOf('(');<br> int b = text.lastIndexOf('+');<br><br> if (a != -1 && b != -1) {<br> ++a;<br> text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup;<br> }<br><br> ret = dg(text);<br> if (ret)<br> break;<br> }<br> return ret;<br> }<br><br> private:<br> int numframes; <br> char** framelist;<br> }<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>