Skip to content

Commit

Permalink
generic stack trace overriding mechanism (#12922)
Browse files Browse the repository at this point in the history
* 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.}
  • Loading branch information
stefantalpalaru authored and Araq committed Dec 29, 2019
1 parent 37e93ea commit ee9ee29
Showing 1 changed file with 33 additions and 10 deletions.
43 changes: 33 additions & 10 deletions lib/system/excpt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit ee9ee29

Please sign in to comment.