Skip to content

Commit 2e1b555

Browse files
timotheecourmildred
authored andcommitted
fix partially nim-lang#13115 (now works for cpp; but still fails for js on openbsd) (nim-lang#16167)
* fix partially nim-lang#13115 properly (works for c,js,cpp,vm; still fails for js on openbsd) * address comment: also test with -d:danger, -d:debug
1 parent 12ac183 commit 2e1b555

File tree

2 files changed

+58
-20
lines changed

2 files changed

+58
-20
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: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,38 @@
1-
discard """
2-
exitcode: 1
3-
targets: "c"
4-
matrix: "-d:debug; -d:release"
5-
outputsub: ''' and works fine! [Exception]'''
6-
"""
1+
const msg = "This char is `" & '\0' & "` and works fine!"
72

8-
# bug #13115
9-
# xxx bug: doesn't yet work for cpp
3+
when defined nim_t13115:
4+
# bug #13115
5+
template fn =
6+
raise newException(Exception, msg)
7+
when defined nim_t13115_static:
8+
static: fn()
9+
fn()
10+
else:
11+
import std/[osproc,strformat,os,strutils]
12+
proc main =
13+
const nim = getCurrentCompilerExe()
14+
const file = currentSourcePath
15+
for b in "c js cpp".split:
16+
when defined(openbsd):
17+
if b == "js":
18+
# xxx bug: pending #13115
19+
# remove special case once nodejs updated >= 12.16.2
20+
# refs https://github.com/nim-lang/Nim/pull/16167#issuecomment-738270751
21+
continue
1022

11-
var msg = "This char is `" & '\0' & "` and works fine!"
12-
raise newException(Exception, msg)
23+
# save CI time by avoiding mostly redundant combinations as far as this bug is concerned
24+
var opts = case b
25+
of "c": @["", "-d:nim_t13115_static", "-d:danger", "-d:debug"]
26+
of "js": @["", "-d:nim_t13115_static"]
27+
else: @[""]
28+
29+
for opt in opts:
30+
let cmd = fmt"{nim} r -b:{b} -d:nim_t13115 {opt} --hints:off {file}"
31+
let (outp, exitCode) = execCmdEx(cmd)
32+
when defined windows:
33+
# `\0` not preserved on windows
34+
doAssert "` and works fine!" in outp, cmd & "\n" & msg
35+
else:
36+
doAssert msg in outp, cmd & "\n" & msg
37+
doAssert exitCode == 1
38+
main()

0 commit comments

Comments
 (0)