Thread overview | ||||||
---|---|---|---|---|---|---|
|
August 04, 2010 [dmd-internals] Backtraces under Linux | ||||
---|---|---|---|---|
| ||||
I just want to ensure this post to digitalmars.D doesn't get lost. 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. http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=114487 module backtrace; // // Provides support for a readable backtrace on a program crash. // // Everything is private - you build this into a library and // link to the library, and bingo (via static this). // // It works by registering a stacktrace handler with the runtime, // which, unlike the default one, provides demangled symbols // rather than just a list of addresses. // private { import core.stdc.signal; import core.stdc.stdlib : free; import core.stdc.string : strlen; import core.runtime; import std.demangle; import std.string; extern (C) int backtrace(void**, size_t); extern (C) char** backtrace_symbols(void**, int); // signal handler for otherwise-fatal thread-specific signals extern (C) void signal_handler(int sig) { string name() { switch (sig) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; case SIGABRT: return "SIGABRT"; default: return ""; } } throw new Error(format("Got signal %s %s", sig, name)); } shared static this() { // set up shared signal handlers for fatal thread-specific signals signal(SIGABRT, &signal_handler); signal(SIGFPE, &signal_handler); signal(SIGILL, &signal_handler); signal(SIGSEGV, &signal_handler); } static this() { // register our trace handler for each thread Runtime.traceHandler = &traceHandler; } Throwable.TraceInfo traceHandler(void * ptr = null) { return new TraceInfo; } class TraceInfo : Throwable.TraceInfo { this() { immutable MAXFRAMES = 128; void*[MAXFRAMES] callstack; numframes = backtrace(callstack.ptr, MAXFRAMES); framelist = backtrace_symbols(callstack.ptr, numframes); } ~this() { free(framelist); } override string toString() const { return null; } // Why does toString require overriding? override int opApply(scope int delegate(ref char[]) dg) { // NOTE: The first 5 frames with the current implementation are // inside core.runtime and the object code, so eliminate // these for readability. immutable FIRSTFRAME = 5; int ret = 0; for(int i = FIRSTFRAME; i < numframes; ++i) { char[] text = framelist[i][0 .. strlen(framelist[i])]; int a = text.lastIndexOf('('); int b = text.lastIndexOf('+'); if (a != -1 && b != -1) { ++a; text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; } ret = dg(text); if (ret) break; } return ret; } private: int numframes; char** framelist; } } Ok, I've added -L--export-dynamic to dmd.conf and done a copy/modify of DefaultTraceInfo from runtime.d to include demangling and catch certain signals. My backtraces now look gorgeous under Linux. I've attached the source for the updated module. Thanks, Dave On 04/08/10 12:39, Sean Kelly wrote: > Graham St Jack Wrote: >> >> Sean, is there any chance of you rolling some of the good stuff in this code into druntime? >> >> In particular, it would be very nice to get symbol names in a stacktrace rather than a bunch of addresses, and even nicer to get a stacktrace on a SIGSEGV. > > 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. module backtrace; // // Provides support for a readable backtrace on a program crash. // // Everything is private - you build this into a library and // link to the library, and bingo (via static this). // // It works by registering a stacktrace handler with the runtime, // which, unlike the default one, provides demangled symbols // rather than just a list of addresses. // private { import core.stdc.signal; import core.stdc.stdlib : free; import core.stdc.string : strlen; import core.runtime; import std.demangle; import std.string; extern (C) int backtrace(void**, size_t); extern (C) char** backtrace_symbols(void**, int); // signal handler for otherwise-fatal thread-specific signals extern (C) void signal_handler(int sig) { string name() { switch (sig) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; case SIGABRT: return "SIGABRT"; default: return ""; } } throw new Error(format("Got signal %s %s", sig, name)); } shared static this() { // set up shared signal handlers for fatal thread-specific signals signal(SIGABRT, &signal_handler); signal(SIGFPE, &signal_handler); signal(SIGILL, &signal_handler); signal(SIGSEGV, &signal_handler); } static this() { // register our trace handler for each thread Runtime.traceHandler = &traceHandler; } Throwable.TraceInfo traceHandler(void * ptr = null) { return new TraceInfo; } class TraceInfo : Throwable.TraceInfo { this() { immutable MAXFRAMES = 128; void*[MAXFRAMES] callstack; numframes = backtrace(callstack.ptr, MAXFRAMES); framelist = backtrace_symbols(callstack.ptr, numframes); } ~this() { free(framelist); } override string toString() const { return null; } // Why does toString require overriding? override int opApply(scope int delegate(ref char[]) dg) { // NOTE: The first 5 frames with the current implementation are // inside core.runtime and the object code, so eliminate // these for readability. immutable FIRSTFRAME = 5; int ret = 0; for(int i = FIRSTFRAME; i < numframes; ++i) { char[] text = framelist[i][0 .. strlen(framelist[i])]; int a = text.lastIndexOf('('); int b = text.lastIndexOf('+'); if (a != -1 && b != -1) { ++a; text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; } ret = dg(text); if (ret) break; } return ret; } private: int numframes; char** framelist; } } Ok, I've added -L--export-dynamic to dmd.conf and done a copy/modify of DefaultTraceInfo from runtime.d to include demangling and catch certain signals. My backtraces now look gorgeous under Linux. I've attached the source for the updated module. Thanks, Dave On 04/08/10 12:39, Sean Kelly wrote: > Graham St Jack Wrote: >> >> Sean, is there any chance of you rolling some of the good stuff in this code into druntime? >> >> In particular, it would be very nice to get symbol names in a stacktrace rather than a bunch of addresses, and even nicer to get a stacktrace on a SIGSEGV. > > 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. module backtrace; // // Provides support for a readable backtrace on a program crash. // // Everything is private - you build this into a library and // link to the library, and bingo (via static this). // // It works by registering a stacktrace handler with the runtime, // which, unlike the default one, provides demangled symbols // rather than just a list of addresses. // private { import core.stdc.signal; import core.stdc.stdlib : free; import core.stdc.string : strlen; import core.runtime; import std.demangle; import std.string; extern (C) int backtrace(void**, size_t); extern (C) char** backtrace_symbols(void**, int); // signal handler for otherwise-fatal thread-specific signals extern (C) void signal_handler(int sig) { string name() { switch (sig) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; case SIGABRT: return "SIGABRT"; default: return ""; } } throw new Error(format("Got signal %s %s", sig, name)); } shared static this() { // set up shared signal handlers for fatal thread-specific signals signal(SIGABRT, &signal_handler); signal(SIGFPE, &signal_handler); signal(SIGILL, &signal_handler); signal(SIGSEGV, &signal_handler); } static this() { // register our trace handler for each thread Runtime.traceHandler = &traceHandler; } Throwable.TraceInfo traceHandler(void * ptr = null) { return new TraceInfo; } class TraceInfo : Throwable.TraceInfo { this() { immutable MAXFRAMES = 128; void*[MAXFRAMES] callstack; numframes = backtrace(callstack.ptr, MAXFRAMES); framelist = backtrace_symbols(callstack.ptr, numframes); } ~this() { free(framelist); } override string toString() const { return null; } // Why does toString require overriding? override int opApply(scope int delegate(ref char[]) dg) { // NOTE: The first 5 frames with the current implementation are // inside core.runtime and the object code, so eliminate // these for readability. immutable FIRSTFRAME = 5; int ret = 0; for(int i = FIRSTFRAME; i < numframes; ++i) { char[] text = framelist[i][0 .. strlen(framelist[i])]; int a = text.lastIndexOf('('); int b = text.lastIndexOf('+'); if (a != -1 && b != -1) { ++a; text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; } ret = dg(text); if (ret) break; } return ret; } private: int numframes; char** framelist; } } Ok, I've added -L--export-dynamic to dmd.conf and done a copy/modify of DefaultTraceInfo from runtime.d to include demangling and catch certain signals. My backtraces now look gorgeous under Linux. I've attached the source for the updated module. Thanks, Dave On 04/08/10 12:39, Sean Kelly wrote: > Graham St Jack Wrote: >> >> Sean, is there any chance of you rolling some of the good stuff in this code into druntime? >> >> In particular, it would be very nice to get symbol names in a stacktrace rather than a bunch of addresses, and even nicer to get a stacktrace on a SIGSEGV. > > 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. module backtrace; // // Provides support for a readable backtrace on a program crash. // // Everything is private - you build this into a library and // link to the library, and bingo (via static this). // // It works by registering a stacktrace handler with the runtime, // which, unlike the default one, provides demangled symbols // rather than just a list of addresses. // private { import core.stdc.signal; import core.stdc.stdlib : free; import core.stdc.string : strlen; import core.runtime; import std.demangle; import std.string; extern (C) int backtrace(void**, size_t); extern (C) char** backtrace_symbols(void**, int); // signal handler for otherwise-fatal thread-specific signals extern (C) void signal_handler(int sig) { string name() { switch (sig) { case SIGSEGV: return "SIGSEGV"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; case SIGABRT: return "SIGABRT"; default: return ""; } } throw new Error(format("Got signal %s %s", sig, name)); } shared static this() { // set up shared signal handlers for fatal thread-specific signals signal(SIGABRT, &signal_handler); signal(SIGFPE, &signal_handler); signal(SIGILL, &signal_handler); signal(SIGSEGV, &signal_handler); } static this() { // register our trace handler for each thread Runtime.traceHandler = &traceHandler; } Throwable.TraceInfo traceHandler(void * ptr = null) { return new TraceInfo; } class TraceInfo : Throwable.TraceInfo { this() { immutable MAXFRAMES = 128; void*[MAXFRAMES] callstack; numframes = backtrace(callstack.ptr, MAXFRAMES); framelist = backtrace_symbols(callstack.ptr, numframes); } ~this() { free(framelist); } override string toString() const { return null; } // Why does toString require overriding? override int opApply(scope int delegate(ref char[]) dg) { // NOTE: The first 5 frames with the current implementation are // inside core.runtime and the object code, so eliminate // these for readability. immutable FIRSTFRAME = 5; int ret = 0; for(int i = FIRSTFRAME; i < numframes; ++i) { char[] text = framelist[i][0 .. strlen(framelist[i])]; int a = text.lastIndexOf('('); int b = text.lastIndexOf('+'); if (a != -1 && b != -1) { ++a; text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; } ret = dg(text); if (ret) break; } return ret; } private: int numframes; char** framelist; } } -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.puremagic.com/pipermail/dmd-internals/attachments/20100804/04dd9d4a/attachment-0001.html> |
August 05, 2010 [dmd-internals] Backtraces under Linux | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jason House | The blocker for adopting this code as-is is that it depends on Phobos. -L--export-dynamic still has to be added to linux/bin/dmd.conf in the install package, and I'm working on a demangler. I'd just copy the one from Phobos, but it works purely with strings using array concatenation and I want to avoid hitting the GC so hard when an exception is thrown. I've discovered that writing such a demangler is kind of a pain because things have to be reordered during demangling (where the qualified name is for function vs. non-function types, for example). Anyway, almost done, but it's taking the backseat to other work ATM. Thanks for the reminder! On Aug 4, 2010, at 5:43 AM, Jason House wrote: > I just want to ensure this post to digitalmars.D doesn't get lost. > > 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. > > http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=114487 > > module backtrace; > > // > // Provides support for a readable backtrace on a program crash. > // > // Everything is private - you build this into a library and > // link to the library, and bingo (via static this). > // > // It works by registering a stacktrace handler with the runtime, > // which, unlike the default one, provides demangled symbols > // rather than just a list of addresses. > // > > private { > > import core.stdc.signal; > import core.stdc.stdlib : free; > import core.stdc.string : strlen; > import core.runtime; > import std.demangle; > import std.string; > > extern (C) int backtrace(void**, size_t); > extern (C) char** backtrace_symbols(void**, int); > > // signal handler for otherwise-fatal thread-specific signals > extern (C) void signal_handler(int sig) { > string name() { > switch (sig) { > case SIGSEGV: return "SIGSEGV"; > case SIGFPE: return "SIGFPE"; > case SIGILL: return "SIGILL"; > case SIGABRT: return "SIGABRT"; > default: return ""; > } > } > > throw new Error(format("Got signal %s %s", sig, name)); > } > > shared static this() { > // set up shared signal handlers for fatal thread-specific signals > signal(SIGABRT, &signal_handler); > signal(SIGFPE, &signal_handler); > signal(SIGILL, &signal_handler); > signal(SIGSEGV, &signal_handler); > } > > static this() { > // register our trace handler for each thread > Runtime.traceHandler = &traceHandler; > } > > Throwable.TraceInfo traceHandler(void * ptr = null) { > return new TraceInfo; > } > > class TraceInfo : Throwable.TraceInfo { > this() { > immutable MAXFRAMES = 128; > void*[MAXFRAMES] callstack; > > numframes = backtrace(callstack.ptr, MAXFRAMES); > framelist = backtrace_symbols(callstack.ptr, numframes); > } > > ~this() { > free(framelist); > } > > override string toString() const { return null; } // Why does toString require overriding? > > override int opApply(scope int delegate(ref char[]) dg) { > // NOTE: The first 5 frames with the current implementation are > // inside core.runtime and the object code, so eliminate > // these for readability. > immutable FIRSTFRAME = 5; > int ret = 0; > > for(int i = FIRSTFRAME; i < numframes; ++i) { > char[] text = framelist[i][0 .. strlen(framelist[i])]; > > int a = text.lastIndexOf('('); > int b = text.lastIndexOf('+'); > > if (a != -1 && b != -1) { > ++a; > text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; > } > > ret = dg(text); > if (ret) > break; > } > return ret; > } > > private: > int numframes; > char** framelist; > } > } > > > > Ok, > > I've added -L--export-dynamic to dmd.conf and done a copy/modify of DefaultTraceInfo from runtime.d to include demangling and catch certain signals. My backtraces now look gorgeous under Linux. > > I've attached the source for the updated module. > > Thanks, > Dave > > On 04/08/10 12:39, Sean Kelly wrote: > > Graham St Jack Wrote: > >> > >> Sean, is there any chance of you rolling some of the good stuff in this code into druntime? > >> > >> In particular, it would be very nice to get symbol names in a stacktrace rather than a bunch of addresses, and even nicer to get a stacktrace on a SIGSEGV. > > > > 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. > > > > > module backtrace; > > // > // Provides support for a readable backtrace on a program crash. > // > // Everything is private - you build this into a library and > // link to the library, and bingo (via static this). > // > // It works by registering a stacktrace handler with the runtime, > // which, unlike the default one, provides demangled symbols > // rather than just a list of addresses. > // > > private { > > import core.stdc.signal; > import core.stdc.stdlib : free; > import core.stdc.string : strlen; > import core.runtime; > import std.demangle; > import std.string; > > extern (C) int backtrace(void**, size_t); > extern (C) char** backtrace_symbols(void**, int); > > // signal handler for otherwise-fatal thread-specific signals > extern (C) void signal_handler(int sig) { > string name() { > switch (sig) { > case SIGSEGV: return "SIGSEGV"; > case SIGFPE: return "SIGFPE"; > case SIGILL: return "SIGILL"; > case SIGABRT: return "SIGABRT"; > default: return ""; > } > } > > throw new Error(format("Got signal %s %s", sig, name)); > } > > shared static this() { > // set up shared signal handlers for fatal thread-specific signals > signal(SIGABRT, &signal_handler); > signal(SIGFPE, &signal_handler); > signal(SIGILL, &signal_handler); > signal(SIGSEGV, &signal_handler); > } > > static this() { > // register our trace handler for each thread > Runtime.traceHandler = &traceHandler; > } > > Throwable.TraceInfo traceHandler(void * ptr = null) { > return new TraceInfo; > } > > class TraceInfo : Throwable.TraceInfo { > this() { > immutable MAXFRAMES = 128; > void*[MAXFRAMES] callstack; > > numframes = backtrace(callstack.ptr, MAXFRAMES); > framelist = backtrace_symbols(callstack.ptr, numframes); > } > > ~this() { > free(framelist); > } > > override string toString() const { return null; } // Why does toString require overriding? > > override int opApply(scope int delegate(ref char[]) dg) { > // NOTE: The first 5 frames with the current implementation are > // inside core.runtime and the object code, so eliminate > // these for readability. > immutable FIRSTFRAME = 5; > int ret = 0; > > for(int i = FIRSTFRAME; i < numframes; ++i) { > char[] text = framelist[i][0 .. strlen(framelist[i])]; > > int a = text.lastIndexOf('('); > int b = text.lastIndexOf('+'); > > if (a != -1 && b != -1) { > ++a; > text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; > } > > ret = dg(text); > if (ret) > break; > } > return ret; > } > > private: > int numframes; > char** framelist; > } > } > > > > Ok, > > I've added -L--export-dynamic to dmd.conf and done a copy/modify of DefaultTraceInfo from runtime.d to include demangling and catch certain signals. My backtraces now look gorgeous under Linux. > > I've attached the source for the updated module. > > Thanks, > Dave > > On 04/08/10 12:39, Sean Kelly wrote: > > Graham St Jack Wrote: > >> > >> Sean, is there any chance of you rolling some of the good stuff in this code into druntime? > >> > >> In particular, it would be very nice to get symbol names in a stacktrace rather than a bunch of addresses, and even nicer to get a stacktrace on a SIGSEGV. > > > > 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. > > > > > module backtrace; > > // > // Provides support for a readable backtrace on a program crash. > // > // Everything is private - you build this into a library and > // link to the library, and bingo (via static this). > // > // It works by registering a stacktrace handler with the runtime, > // which, unlike the default one, provides demangled symbols > // rather than just a list of addresses. > // > > private { > > import core.stdc.signal; > import core.stdc.stdlib : free; > import core.stdc.string : strlen; > import core.runtime; > import std.demangle; > import std.string; > > extern (C) int backtrace(void**, size_t); > extern (C) char** backtrace_symbols(void**, int); > > // signal handler for otherwise-fatal thread-specific signals > extern (C) void signal_handler(int sig) { > string name() { > switch (sig) { > case SIGSEGV: return "SIGSEGV"; > case SIGFPE: return "SIGFPE"; > case SIGILL: return "SIGILL"; > case SIGABRT: return "SIGABRT"; > default: return ""; > } > } > > throw new Error(format("Got signal %s %s", sig, name)); > } > > shared static this() { > // set up shared signal handlers for fatal thread-specific signals > signal(SIGABRT, &signal_handler); > signal(SIGFPE, &signal_handler); > signal(SIGILL, &signal_handler); > signal(SIGSEGV, &signal_handler); > } > > static this() { > // register our trace handler for each thread > Runtime.traceHandler = &traceHandler; > } > > Throwable.TraceInfo traceHandler(void * ptr = null) { > return new TraceInfo; > } > > class TraceInfo : Throwable.TraceInfo { > this() { > immutable MAXFRAMES = 128; > void*[MAXFRAMES] callstack; > > numframes = backtrace(callstack.ptr, MAXFRAMES); > framelist = backtrace_symbols(callstack.ptr, numframes); > } > > ~this() { > free(framelist); > } > > override string toString() const { return null; } // Why does toString require overriding? > > override int opApply(scope int delegate(ref char[]) dg) { > // NOTE: The first 5 frames with the current implementation are > // inside core.runtime and the object code, so eliminate > // these for readability. > immutable FIRSTFRAME = 5; > int ret = 0; > > for(int i = FIRSTFRAME; i < numframes; ++i) { > char[] text = framelist[i][0 .. strlen(framelist[i])]; > > int a = text.lastIndexOf('('); > int b = text.lastIndexOf('+'); > > if (a != -1 && b != -1) { > ++a; > text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; > } > > ret = dg(text); > if (ret) > break; > } > return ret; > } > > private: > int numframes; > char** framelist; > } > } > > > > Ok, > > I've added -L--export-dynamic to dmd.conf and done a copy/modify of DefaultTraceInfo from runtime.d to include demangling and catch certain signals. My backtraces now look gorgeous under Linux. > > I've attached the source for the updated module. > > Thanks, > Dave > > On 04/08/10 12:39, Sean Kelly wrote: > > Graham St Jack Wrote: > >> > >> Sean, is there any chance of you rolling some of the good stuff in this code into druntime? > >> > >> In particular, it would be very nice to get symbol names in a stacktrace rather than a bunch of addresses, and even nicer to get a stacktrace on a SIGSEGV. > > > > 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. > > > > > module backtrace; > > // > // Provides support for a readable backtrace on a program crash. > // > // Everything is private - you build this into a library and > // link to the library, and bingo (via static this). > // > // It works by registering a stacktrace handler with the runtime, > // which, unlike the default one, provides demangled symbols > // rather than just a list of addresses. > // > > private { > > import core.stdc.signal; > import core.stdc.stdlib : free; > import core.stdc.string : strlen; > import core.runtime; > import std.demangle; > import std.string; > > extern (C) int backtrace(void**, size_t); > extern (C) char** backtrace_symbols(void**, int); > > // signal handler for otherwise-fatal thread-specific signals > extern (C) void signal_handler(int sig) { > string name() { > switch (sig) { > case SIGSEGV: return "SIGSEGV"; > case SIGFPE: return "SIGFPE"; > case SIGILL: return "SIGILL"; > case SIGABRT: return "SIGABRT"; > default: return ""; > } > } > > throw new Error(format("Got signal %s %s", sig, name)); > } > > shared static this() { > // set up shared signal handlers for fatal thread-specific signals > signal(SIGABRT, &signal_handler); > signal(SIGFPE, &signal_handler); > signal(SIGILL, &signal_handler); > signal(SIGSEGV, &signal_handler); > } > > static this() { > // register our trace handler for each thread > Runtime.traceHandler = &traceHandler; > } > > Throwable.TraceInfo traceHandler(void * ptr = null) { > return new TraceInfo; > } > > class TraceInfo : Throwable.TraceInfo { > this() { > immutable MAXFRAMES = 128; > void*[MAXFRAMES] callstack; > > numframes = backtrace(callstack.ptr, MAXFRAMES); > framelist = backtrace_symbols(callstack.ptr, numframes); > } > > ~this() { > free(framelist); > } > > override string toString() const { return null; } // Why does toString require overriding? > > override int opApply(scope int delegate(ref char[]) dg) { > // NOTE: The first 5 frames with the current implementation are > // inside core.runtime and the object code, so eliminate > // these for readability. > immutable FIRSTFRAME = 5; > int ret = 0; > > for(int i = FIRSTFRAME; i < numframes; ++i) { > char[] text = framelist[i][0 .. strlen(framelist[i])]; > > int a = text.lastIndexOf('('); > int b = text.lastIndexOf('+'); > > if (a != -1 && b != -1) { > ++a; > text = format("%s%s%s", text[0..a], demangle(text[a..b].idup), text[b..$]).dup; > } > > ret = dg(text); > if (ret) > break; > } > return ret; > } > > private: > int numframes; > char** framelist; > } > } > > > _______________________________________________ > dmd-internals mailing list > dmd-internals at puremagic.com > http://lists.puremagic.com/mailman/listinfo/dmd-internals -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.puremagic.com/pipermail/dmd-internals/attachments/20100805/6f2741e2/attachment-0001.html> |
August 06, 2010 [dmd-internals] Backtraces under Linux | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Can the demangling be done lazily? That is, you only demangle when the stack-trace is printed?
If stack traces must be constructed at throw time and that involves heavy GC usage, this is a non-starter, because exceptions can be used for flow control, not just printing.
-Steve
>
>From: Sean Kelly <sean at invisibleduck.org>
>To: Discuss the internals of DMD <dmd-internals at puremagic.com>
>Sent: Thu, August 5, 2010 7:11:35 PM
>Subject: Re: [dmd-internals] Backtraces under Linux
>
>
>The blocker for adopting this code as-is is that it depends on Phobos.
> -L--export-dynamic still has to be added to linux/bin/dmd.conf in the install
>package, and I'm working on a demangler. I'd just copy the one from Phobos, but
>
>it works purely with strings using array concatenation and I want to avoid hitting the GC so hard when an exception is thrown. I've discovered that writing such a demangler is kind of a pain because things have to be reordered during demangling (where the qualified name is for function vs. non-function types, for example). Anyway, almost done, but it's taking the backseat to other
>
>work ATM. Thanks for the reminder!
>
>On Aug 4, 2010, at 5:43 AM, Jason House wrote:
>
>I just want to ensure this post to digitalmars.D doesn't get lost.
|
August 06, 2010 [dmd-internals] Backtraces under Linux | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steve Schveighoffer | Yeah, it would be done lazily. There's only one additional allocation when an exception is thrown if tracing is turned on.
On Aug 6, 2010, at 4:47 AM, Steve Schveighoffer wrote:
> Can the demangling be done lazily? That is, you only demangle when the stack-trace is printed?
>
> If stack traces must be constructed at throw time and that involves heavy GC usage, this is a non-starter, because exceptions can be used for flow control, not just printing.
>
> -Steve
>
>
>
>>
>> From: Sean Kelly <sean at invisibleduck.org>
>> To: Discuss the internals of DMD <dmd-internals at puremagic.com>
>> Sent: Thu, August 5, 2010 7:11:35 PM
>> Subject: Re: [dmd-internals] Backtraces under Linux
>>
>>
>> The blocker for adopting this code as-is is that it depends on Phobos. -L--export-dynamic still has to be added to linux/bin/dmd.conf in the install package, and I'm working on a demangler. I'd just copy the one from Phobos, but
>>
>> it works purely with strings using array concatenation and I want to avoid hitting the GC so hard when an exception is thrown. I've discovered that writing such a demangler is kind of a pain because things have to be reordered during demangling (where the qualified name is for function vs. non-function types, for example). Anyway, almost done, but it's taking the backseat to other
>>
>> work ATM. Thanks for the reminder!
>>
>> On Aug 4, 2010, at 5:43 AM, Jason House wrote:
>>
>> I just want to ensure this post to digitalmars.D doesn't get lost.
>
>
>
>
> _______________________________________________
> dmd-internals mailing list
> dmd-internals at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-internals
|
Copyright © 1999-2021 by the D Language Foundation