Skip to content

Commit b39e5dd

Browse files
committed
fix #13115 properly (works for c,js,cpp,vm)
1 parent 808ab7e commit b39e5dd

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

lib/system/excpt.nim

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import std/private/miscdollars
1414
import stacktraces
1515

16+
const noStacktraceAvailable = "No stack traceback available\n"
17+
1618
var
1719
errorMessageWriter*: (proc(msg: string) {.tags: [WriteIOEffect], benign,
1820
nimcall.})
@@ -36,6 +38,10 @@ else:
3638
proc writeToStdErr(msg: cstring, length: int) =
3739
discard MessageBoxA(nil, msg, nil, 0)
3840

41+
proc writeToStdErr(msg: string) {.inline.} =
42+
# fix bug #13115: handles correctly '\0' unlike default implicit conversion to cstring
43+
writeToStdErr(msg.cstring, msg.len)
44+
3945
proc showErrorMessage(data: cstring, length: int) {.gcsafe, raises: [].} =
4046
var toWrite = true
4147
if errorMessageWriter != nil:
@@ -51,6 +57,9 @@ proc showErrorMessage(data: cstring, length: int) {.gcsafe, raises: [].} =
5157
else:
5258
writeToStdErr(data, length)
5359

60+
proc showErrorMessage2(data: string) {.inline.} =
61+
showErrorMessage(data.cstring, data.len)
62+
5463
proc chckIndx(i, a, b: int): int {.inline, compilerproc, benign.}
5564
proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.}
5665
proc chckRangeF(x, a, b: float): float {.inline, compilerproc, benign.}
@@ -123,11 +132,11 @@ proc popSafePoint {.compilerRtl, inl.} =
123132
proc pushCurrentException(e: sink(ref Exception)) {.compilerRtl, inl.} =
124133
e.up = currException
125134
currException = e
126-
#showErrorMessage "A"
135+
#showErrorMessage2 "A"
127136

128137
proc popCurrentException {.compilerRtl, inl.} =
129138
currException = currException.up
130-
#showErrorMessage "B"
139+
#showErrorMessage2 "B"
131140

132141
proc popCurrentExceptionEx(id: uint) {.compilerRtl.} =
133142
discard "only for bootstrapping compatbility"
@@ -305,15 +314,15 @@ when hasSomeStackTrace:
305314
auxWriteStackTraceWithOverride(s)
306315
elif NimStackTrace:
307316
if framePtr == nil:
308-
add(s, "No stack traceback available\n")
317+
add(s, noStacktraceAvailable)
309318
else:
310319
add(s, "Traceback (most recent call last)\n")
311320
auxWriteStackTrace(framePtr, s)
312321
elif defined(nativeStackTrace) and nativeStackTraceSupported:
313322
add(s, "Traceback from system (most recent call last)\n")
314323
auxWriteStackTraceWithBacktrace(s)
315324
else:
316-
add(s, "No stack traceback available\n")
325+
add(s, noStacktraceAvailable)
317326

318327
proc rawWriteStackTrace(s: var seq[StackTraceEntry]) =
319328
when defined(nimStackTraceOverride):
@@ -363,7 +372,7 @@ proc reportUnhandledErrorAux(e: ref Exception) {.nodestroy.} =
363372
if onUnhandledException != nil:
364373
onUnhandledException(buf)
365374
else:
366-
showErrorMessage(buf, buf.len)
375+
showErrorMessage2(buf)
367376
`=destroy`(buf)
368377
else:
369378
# ugly, but avoids heap allocations :-)
@@ -504,16 +513,16 @@ proc writeStackTrace() =
504513
when hasSomeStackTrace:
505514
var s = ""
506515
rawWriteStackTrace(s)
507-
cast[proc (s: cstring, length: int) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)(s, s.len)
508516
else:
509-
cast[proc (s: cstring, length: int) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)("No stack traceback available\n", 32)
517+
let s = noStacktraceAvailable
518+
cast[proc (s: string) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage2)(s)
510519

511520
proc getStackTrace(): string =
512521
when hasSomeStackTrace:
513522
result = ""
514523
rawWriteStackTrace(result)
515524
else:
516-
result = "No stack traceback available\n"
525+
result = noStacktraceAvailable
517526

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

549558
proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
@@ -627,13 +636,16 @@ when not defined(noSignalHandler) and not defined(useNimRtl):
627636
var buf = newStringOfCap(2000)
628637
rawWriteStackTrace(buf)
629638
processSignal(sign, buf.add) # nice hu? currying a la Nim :-)
630-
showErrorMessage(buf, buf.len)
639+
showErrorMessage2(buf)
631640
when not usesDestructors: GC_enable()
632641
else:
633642
var msg: cstring
634643
template asgn(y) =
635644
msg = y
636645
processSignal(sign, asgn)
646+
# xxx use string for msg instead of cstring, and here use showErrorMessage2(msg)
647+
# unless there's a good reason to use cstring in signal handler to avoid
648+
# using gc?
637649
showErrorMessage(msg, msg.len)
638650
quit(1) # always quit when SIGABRT
639651

tests/exception/t13115.nim

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
discard """
22
exitcode: 1
3-
targets: "c"
3+
targets: "c js cpp"
44
matrix: "-d:debug; -d:release"
55
outputsub: ''' and works fine! [Exception]'''
66
"""
77

88
# bug #13115
9-
# xxx bug: doesn't yet work for cpp
109

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

0 commit comments

Comments
 (0)