diff options
-rw-r--r-- | lib/system/ansi_c.nim | 5 | ||||
-rw-r--r-- | lib/system/excpt.nim | 25 | ||||
-rw-r--r-- | tests/exception/t13115.nim | 13 |
3 files changed, 33 insertions, 10 deletions
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 0b4b25992..4839407c1 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -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) diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 04c5d3ce8..f73a88e30 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -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: @@ -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.} @@ -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 :-) @@ -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: @@ -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: @@ -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: [].} = @@ -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() = diff --git a/tests/exception/t13115.nim b/tests/exception/t13115.nim new file mode 100644 index 000000000..9d88bbeda --- /dev/null +++ b/tests/exception/t13115.nim @@ -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) \ No newline at end of file |