generic stack trace overriding mechanism (#12922)

* libbacktrace support

* switch to a generic stack trace overriding mechanism

When "nimStackTraceOverride" is defined, once of the imported modules
can register its own procedure to replace the default stack trace
generation by calling `registerStackTraceOverride(myOwnProc)`.

Tested with `./koch boot -d:release --debugger:native -d:nimStackTraceOverride --import:libbacktrace`
for the compiler itself and `./bin/nim c -r -f --stacktrace:off --debugger:native -d:nimStackTraceOverride --import:libbacktrace foo.nim`
for an external program.

* make the StackTraceOverrideProc {.noinline.}
This commit is contained in:
Ștefan Talpalaru
2019-12-29 15:46:01 +01:00
committed by Andreas Rumpf
parent 37e93eab66
commit ee9ee297d8

View File

@@ -140,8 +140,23 @@ proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
const
nativeStackTraceSupported* = (defined(macosx) or defined(linux)) and
not NimStackTrace
hasSomeStackTrace = NimStackTrace or
defined(nativeStackTrace) and nativeStackTraceSupported
hasSomeStackTrace = NimStackTrace or defined(nimStackTraceOverride) or
(defined(nativeStackTrace) and nativeStackTraceSupported)
when defined(nimStackTraceOverride):
type StackTraceOverrideProc* = proc (): string {.nimcall, noinline, benign, raises: [], tags: [].}
## Procedure type for overriding the default stack trace.
var stackTraceOverrideGetTraceback: StackTraceOverrideProc = proc(): string {.noinline.} =
result = "Stack trace override procedure not registered.\n"
proc registerStackTraceOverride*(overrideProc: StackTraceOverrideProc) =
## Override the default stack trace inside rawWriteStackTrace() with your
## own procedure.
stackTraceOverrideGetTraceback = overrideProc
proc auxWriteStackTraceWithOverride(s: var string) =
add(s, stackTraceOverrideGetTraceback())
when defined(nativeStacktrace) and nativeStackTraceSupported:
type
@@ -289,7 +304,10 @@ proc stackTraceAvailable*(): bool
when hasSomeStackTrace:
proc rawWriteStackTrace(s: var string) =
when NimStackTrace:
when defined(nimStackTraceOverride):
add(s, "Traceback (most recent call last, using override)\n")
auxWriteStackTraceWithOverride(s)
elif NimStackTrace:
if framePtr == nil:
add(s, "No stack traceback available\n")
else:
@@ -308,7 +326,9 @@ when hasSomeStackTrace:
s = @[]
proc stackTraceAvailable(): bool =
when NimStackTrace:
when defined(nimStackTraceOverride):
result = true
elif NimStackTrace:
if framePtr == nil:
result = false
else:
@@ -443,12 +463,15 @@ proc raiseExceptionEx(e: sink(ref Exception), ename, procname, filename: cstring
line: int) {.compilerRtl, nodestroy.} =
if e.name.isNil: e.name = ename
when hasSomeStackTrace:
if e.trace.len == 0:
rawWriteStackTrace(e.trace)
elif framePtr != nil:
e.trace.add reraisedFrom(reraisedFromBegin)
auxWriteStackTrace(framePtr, e.trace)
e.trace.add reraisedFrom(reraisedFromEnd)
when defined(nimStackTraceOverride):
e.trace = @[]
elif NimStackTrace:
if e.trace.len == 0:
rawWriteStackTrace(e.trace)
elif framePtr != nil:
e.trace.add reraisedFrom(reraisedFromBegin)
auxWriteStackTrace(framePtr, e.trace)
e.trace.add reraisedFrom(reraisedFromEnd)
else:
if procname != nil and filename != nil:
e.trace.add StackTraceEntry(procname: procname, filename: filename, line: line)