mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-24 00:05:25 +00:00
stacktraces can now show custom runtime msgs per frame (#13351)
* stacktraces can now show custom runtime msgs * improve tests/stdlib/tstackframes.nim * fix test for --gc:arc * test --stacktraceMsgs:on and --stacktraceMsgs:off * --stacktracemsgs:off by default
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
const NimStackTraceMsgs =
|
||||
when defined(nimHasStacktraceMsgs): compileOption("stacktraceMsgs")
|
||||
else: false
|
||||
|
||||
type
|
||||
RootEffect* {.compilerproc.} = object of RootObj ## \
|
||||
## Base effect class.
|
||||
@@ -16,6 +20,11 @@ type
|
||||
procname*: cstring ## Name of the proc that is currently executing.
|
||||
line*: int ## Line number of the proc that is currently executing.
|
||||
filename*: cstring ## Filename of the proc that is currently executing.
|
||||
when NimStackTraceMsgs:
|
||||
frameMsg*: string ## When a stacktrace is generated in a given frame and
|
||||
## rendered at a later time, we should ensure the stacktrace
|
||||
## data isn't invalidated; any pointer into PFrame is
|
||||
## subject to being invalidated so shouldn't be stored.
|
||||
|
||||
Exception* {.compilerproc, magic: "Exception".} = object of RootObj ## \
|
||||
## Base exception class.
|
||||
|
||||
@@ -53,6 +53,8 @@ type
|
||||
len: int
|
||||
prev: ptr GcFrameHeader
|
||||
|
||||
when NimStackTraceMsgs:
|
||||
var frameMsgBuf* {.threadvar.}: string
|
||||
var
|
||||
framePtr {.threadvar.}: PFrame
|
||||
excHandler {.threadvar.}: PSafePoint
|
||||
@@ -224,10 +226,17 @@ proc auxWriteStackTrace(f: PFrame; s: var seq[StackTraceEntry]) =
|
||||
s[last] = StackTraceEntry(procname: it.procname,
|
||||
line: it.line,
|
||||
filename: it.filename)
|
||||
when NimStackTraceMsgs:
|
||||
let first = if it.prev == nil: 0 else: it.prev.frameMsgLen
|
||||
if it.frameMsgLen > first:
|
||||
s[last].frameMsg.setLen(it.frameMsgLen - first)
|
||||
# somehow string slicing not available here
|
||||
for i in first .. it.frameMsgLen-1:
|
||||
s[last].frameMsg[i-first] = frameMsgBuf[i]
|
||||
it = it.prev
|
||||
dec last
|
||||
|
||||
template addFrameEntry(s, f: untyped) =
|
||||
template addFrameEntry(s: var string, f: StackTraceEntry|PFrame) =
|
||||
var oldLen = s.len
|
||||
add(s, f.filename)
|
||||
if f.line > 0:
|
||||
@@ -236,6 +245,12 @@ template addFrameEntry(s, f: untyped) =
|
||||
add(s, ')')
|
||||
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
|
||||
add(s, f.procname)
|
||||
when NimStackTraceMsgs:
|
||||
when type(f) is StackTraceEntry:
|
||||
add(s, f.frameMsg)
|
||||
else:
|
||||
var first = if f.prev == nil: 0 else: f.prev.frameMsgLen
|
||||
for i in first..<f.frameMsgLen: add(s, frameMsgBuf[i])
|
||||
add(s, "\n")
|
||||
|
||||
proc `$`(s: seq[StackTraceEntry]): string =
|
||||
@@ -519,7 +534,12 @@ proc callDepthLimitReached() {.noinline.} =
|
||||
quit(1)
|
||||
|
||||
proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
|
||||
s.calldepth = if framePtr == nil: 0 else: framePtr.calldepth+1
|
||||
if framePtr == nil:
|
||||
s.calldepth = 0
|
||||
when NimStackTraceMsgs: s.frameMsgLen = 0
|
||||
else:
|
||||
s.calldepth = framePtr.calldepth+1
|
||||
when NimStackTraceMsgs: s.frameMsgLen = framePtr.frameMsgLen
|
||||
s.prev = framePtr
|
||||
framePtr = s
|
||||
if s.calldepth == nimCallDepthLimit: callDepthLimitReached()
|
||||
|
||||
Reference in New Issue
Block a user