Skip to content

Commit

Permalink
fix nim-lang#13115 properly (works for c,js,cpp,vm)
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed Nov 28, 2020
1 parent 157e782 commit 45e2250
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
32 changes: 22 additions & 10 deletions lib/system/excpt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import std/private/miscdollars
import stacktraces

const noStacktraceAvailable = "No stack traceback available\n"

var
errorMessageWriter*: (proc(msg: string) {.tags: [WriteIOEffect], benign,
nimcall.})
Expand All @@ -36,6 +38,10 @@ else:
proc writeToStdErr(msg: cstring, length: int) =
discard MessageBoxA(nil, msg, nil, 0)

proc writeToStdErr(msg: string) {.inline.} =
# fix bug #13115: handles correctly '\0' unlike default implicit conversion to cstring
writeToStdErr(msg.cstring, msg.len)

proc showErrorMessage(data: cstring, length: int) {.gcsafe, raises: [].} =
var toWrite = true
if errorMessageWriter != nil:
Expand All @@ -51,6 +57,9 @@ proc showErrorMessage(data: cstring, length: int) {.gcsafe, raises: [].} =
else:
writeToStdErr(data, length)

proc showErrorMessage2(data: string) {.inline.} =
showErrorMessage(data.cstring, data.len)

proc chckIndx(i, a, b: int): int {.inline, compilerproc, benign.}
proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.}
proc chckRangeF(x, a, b: float): float {.inline, compilerproc, benign.}
Expand Down Expand Up @@ -123,11 +132,11 @@ proc popSafePoint {.compilerRtl, inl.} =
proc pushCurrentException(e: sink(ref Exception)) {.compilerRtl, inl.} =
e.up = currException
currException = e
#showErrorMessage "A"
#showErrorMessage2 "A"

proc popCurrentException {.compilerRtl, inl.} =
currException = currException.up
#showErrorMessage "B"
#showErrorMessage2 "B"

proc popCurrentExceptionEx(id: uint) {.compilerRtl.} =
discard "only for bootstrapping compatbility"
Expand Down Expand Up @@ -305,15 +314,15 @@ when hasSomeStackTrace:
auxWriteStackTraceWithOverride(s)
elif NimStackTrace:
if framePtr == nil:
add(s, "No stack traceback available\n")
add(s, noStacktraceAvailable)
else:
add(s, "Traceback (most recent call last)\n")
auxWriteStackTrace(framePtr, s)
elif defined(nativeStackTrace) and nativeStackTraceSupported:
add(s, "Traceback from system (most recent call last)\n")
auxWriteStackTraceWithBacktrace(s)
else:
add(s, "No stack traceback available\n")
add(s, noStacktraceAvailable)

proc rawWriteStackTrace(s: var seq[StackTraceEntry]) =
when defined(nimStackTraceOverride):
Expand Down Expand Up @@ -363,7 +372,7 @@ proc reportUnhandledErrorAux(e: ref Exception) {.nodestroy.} =
if onUnhandledException != nil:
onUnhandledException(buf)
else:
showErrorMessage(buf, buf.len)
showErrorMessage2(buf)
`=destroy`(buf)
else:
# ugly, but avoids heap allocations :-)
Expand Down Expand Up @@ -504,16 +513,16 @@ proc writeStackTrace() =
when hasSomeStackTrace:
var s = ""
rawWriteStackTrace(s)
cast[proc (s: cstring, length: int) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)(s, s.len)
else:
cast[proc (s: cstring, length: int) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)("No stack traceback available\n", 32)
let s = noStacktraceAvailable
cast[proc (s: string) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage2)(s)

proc getStackTrace(): string =
when hasSomeStackTrace:
result = ""
rawWriteStackTrace(result)
else:
result = "No stack traceback available\n"
result = noStacktraceAvailable

proc getStackTrace(e: ref Exception): string =
if not isNil(e):
Expand Down Expand Up @@ -543,7 +552,7 @@ proc callDepthLimitReached() {.noinline.} =
$nimCallDepthLimit & " function calls). You can change it with " &
"-d:nimCallDepthLimit=<int> but really try to avoid deep " &
"recursions instead.\n"
showErrorMessage(msg, msg.len)
showErrorMessage2(msg)
quit(1)

proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
Expand Down Expand Up @@ -627,13 +636,16 @@ when not defined(noSignalHandler) and not defined(useNimRtl):
var buf = newStringOfCap(2000)
rawWriteStackTrace(buf)
processSignal(sign, buf.add) # nice hu? currying a la Nim :-)
showErrorMessage(buf, buf.len)
showErrorMessage2(buf)
when not usesDestructors: GC_enable()
else:
var msg: cstring
template asgn(y) =
msg = y
processSignal(sign, asgn)
# xxx use string for msg instead of cstring, and here use showErrorMessage2(msg)
# unless there's a good reason to use cstring in signal handler to avoid
# using gc?
showErrorMessage(msg, msg.len)
quit(1) # always quit when SIGABRT

Expand Down
13 changes: 7 additions & 6 deletions tests/exception/t13115.nim
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
discard """
exitcode: 1
targets: "c"
targets: "c js cpp"
matrix: "-d:debug; -d:release"
outputsub: '''t13115.nim(13) t13115
Error: unhandled exception: This char is'''
outputsub: ''' and works fine! [Exception]'''
"""

const b_null: char = 0.char
var msg = "This char is `" & $b_null & "` and works fine!"
# bug #13115

raise newException(Exception, msg)
template fn =
var msg = "This char is `" & '\0' & "` and works fine!"
raise newException(Exception, msg)
# static: fn() # would also work
fn()

0 comments on commit 45e2250

Please sign in to comment.