Skip to content

Commit

Permalink
fix #13115 (#15930)
Browse files Browse the repository at this point in the history
* fix #13115

* fix testament
  • Loading branch information
ringabout authored Nov 27, 2020
1 parent bc1db0d commit c555525
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 10 deletions.
5 changes: 5 additions & 0 deletions lib/system/ansi_c.nim
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ proc c_fwrite*(buf: pointer, size, n: csize_t, f: CFilePtr): cint {.
proc c_fflush(f: CFilePtr): cint {.
importc: "fflush", header: "<stdio.h>".}

proc rawWriteString*(f: CFilePtr, s: cstring, length: int) {.compilerproc, nonReloadable, inline.} =
# we cannot throw an exception here!
discard c_fwrite(s, 1, cast[csize_t](length), f)
discard c_fflush(f)

proc rawWrite*(f: CFilePtr, s: cstring) {.compilerproc, nonReloadable, inline.} =
# we cannot throw an exception here!
discard c_fwrite(s, 1, cast[csize_t](s.len), f)
Expand Down
25 changes: 15 additions & 10 deletions lib/system/excpt.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ when defined(windows):

when not defined(windows) or not defined(guiapp):
proc writeToStdErr(msg: cstring) = rawWrite(cstderr, msg)
proc writeToStdErr(msg: cstring, length: int) =
rawWriteString(cstderr, msg, length)
else:
proc MessageBoxA(hWnd: pointer, lpText, lpCaption: cstring, uType: int): int32 {.
header: "<windows.h>", nodecl.}
proc writeToStdErr(msg: cstring) =
discard MessageBoxA(nil, msg, nil, 0)
proc writeToStdErr(msg: cstring, length: int) =
discard MessageBoxA(nil, msg, nil, 0)

proc showErrorMessage(data: cstring) {.gcsafe, raises: [].} =
proc showErrorMessage(data: cstring, length: int) {.gcsafe, raises: [].} =
var toWrite = true
if errorMessageWriter != nil:
try:
Expand All @@ -45,7 +49,7 @@ proc showErrorMessage(data: cstring) {.gcsafe, raises: [].} =
# stderr not available by default, use the LOG session
echo data
else:
writeToStdErr(data)
writeToStdErr(data, length)

proc chckIndx(i, a, b: int): int {.inline, compilerproc, benign.}
proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.}
Expand Down Expand Up @@ -359,7 +363,7 @@ proc reportUnhandledErrorAux(e: ref Exception) {.nodestroy.} =
if onUnhandledException != nil:
onUnhandledException(buf)
else:
showErrorMessage(buf)
showErrorMessage(buf, buf.len)
`=destroy`(buf)
else:
# ugly, but avoids heap allocations :-)
Expand Down Expand Up @@ -388,7 +392,7 @@ proc reportUnhandledErrorAux(e: ref Exception) {.nodestroy.} =
if onUnhandledException != nil:
onUnhandledException($tbuf())
else:
showErrorMessage(tbuf())
showErrorMessage(tbuf(), L)

proc reportUnhandledError(e: ref Exception) {.nodestroy.} =
if unhandledExceptionHook != nil:
Expand Down Expand Up @@ -500,9 +504,9 @@ proc writeStackTrace() =
when hasSomeStackTrace:
var s = ""
rawWriteStackTrace(s)
cast[proc (s: cstring) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)(s)
cast[proc (s: cstring, length: int) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)(s, s.len)
else:
cast[proc (s: cstring) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)("No stack traceback available\n")
cast[proc (s: cstring, length: int) {.noSideEffect, tags: [], nimcall, raises: [].}](showErrorMessage)("No stack traceback available\n", 32)

proc getStackTrace(): string =
when hasSomeStackTrace:
Expand Down Expand Up @@ -535,10 +539,11 @@ const nimCallDepthLimit {.intdefine.} = 2000

proc callDepthLimitReached() {.noinline.} =
writeStackTrace()
showErrorMessage("Error: call depth limit reached in a debug build (" &
let msg = "Error: call depth limit reached in a debug build (" &
$nimCallDepthLimit & " function calls). You can change it with " &
"-d:nimCallDepthLimit=<int> but really try to avoid deep " &
"recursions instead.\n")
"recursions instead.\n"
showErrorMessage(msg, msg.len)
quit(1)

proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
Expand Down Expand Up @@ -622,14 +627,14 @@ 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)
showErrorMessage(buf, buf.len)
when not usesDestructors: GC_enable()
else:
var msg: cstring
template asgn(y) =
msg = y
processSignal(sign, asgn)
showErrorMessage(msg)
showErrorMessage(msg, msg.len)
quit(1) # always quit when SIGABRT

proc registerSignalHandler() =
Expand Down
13 changes: 13 additions & 0 deletions tests/exception/t13115.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
discard """
exitcode: 1
targets: "c"
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!"

raise newException(Exception, msg)

0 comments on commit c555525

Please sign in to comment.