From 1a953168b72d55ee862ac072fd2a03918a31d74b Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Tue, 23 Jun 2020 22:09:10 -0700 Subject: [PATCH] old superseded fix for #10343 D20200623T225224 --- compiler/cgen.nim | 2 ++ lib/system.nim | 2 -- lib/system/ansi_c.nim | 1 + lib/system/excpt.nim | 6 ++-- lib/system/io.nim | 62 +++++++++++++++++++++++++++++++++++++++ tests/exception/t9657.nim | 12 +++++--- 6 files changed, 77 insertions(+), 8 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index cd02ba9b11d19..eeb7b3acd7cdb 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1374,11 +1374,13 @@ proc genMainProc(m: BModule) = "}$N$N" NimMainProc = + # "void wrapNimMain(void (*fun_ptr)());$N" & "N_CDECL(void, NimMain)(void) {$N" & "\tvoid (*volatile inner)(void);$N" & "$4" & "\tinner = NimMainInner;$N" & "$2" & + # "\twrapNimMain(*inner);$N" & "\t(*inner)();$N" & "}$N$N" diff --git a/lib/system.nim b/lib/system.nim index 8224546268150..93de66d9d607a 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -54,7 +54,6 @@ type include "system/basic_types" - proc compileOption*(option: string): bool {. magic: "CompileOption", noSideEffect.} ## Can be used to determine an `on|off` compile-time option. Example: @@ -3026,7 +3025,6 @@ when defined(genode): # Perform application initialization # and return to thread entrypoint. - import system/widestrs export widestrs diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 0b4b259921222..2a85ad8330612 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -158,5 +158,6 @@ 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) discard c_fflush(f) + # todo: same treatment as D20190117T013551 in case `c_fwrite` fails {.pop.} diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 089048163c13d..83376f4e1bca7 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -569,10 +569,12 @@ when defined(cpp) and appType != "lib" and not gotoBasedExceptions and proc setTerminate(handler: proc() {.noconv.}) {.importc: "std::set_terminate", header: "".} + setTerminate proc() {.noconv.} = # Remove ourself as a handler, reinstalling the default handler. setTerminate(nil) + var msg = "Unknown error in unexpected exception handler" try: {.emit: "#if !defined(_MSC_VER) || (_MSC_VER >= 1923)".} @@ -594,8 +596,8 @@ when defined(cpp) and appType != "lib" and not gotoBasedExceptions and # stderr not available by default, use the LOG session echo msg else: - writeToStdErr msg & "\n" - + proc writeToStdErrRobust(msg: string) {.importc.} + writeToStdErrRobust msg & "\n" quit 1 when not defined(noSignalHandler) and not defined(useNimRtl): diff --git a/lib/system/io.nim b/lib/system/io.nim index 4820572147a62..4fca1c4da4cae 100644 --- a/lib/system/io.nim +++ b/lib/system/io.nim @@ -850,3 +850,65 @@ iterator lines*(f: File): TaintedString {.tags: [ReadIOEffect].} = ## result.lines += 1 var res = TaintedString(newStringOfCap(80)) while f.readLine(res): yield res + +when defined(cpp): + {.emit:""" +NIM_EXTERNC int fd_is_valid(int fd) { + return fcntl(fd, F_GETFD) != -1 || errno != EBADF; +} +""".} + +# NIM_EXP +when false: +# proc wrapNimMain(fun: proc(){.cdecl.}) {.exportc.} = + proc wrapNimMain(fun: proc(){.cdecl.}) {.exportc, compilerproc.} = +# proc wrapNimMain(fun: proc(){.cdecl.}) {.compilerproc.} = + ## used to catch un-caught exceptions instead of falling through + ## `std::terminate`, for example allows to fix #10343 + # Seems simpler than `std::set_terminate` alternatives. + fun() + when defined(cpp): + proc fd_is_valid(fd:cint): cint {.cdecl, importc.} + try: + fun() + except Exception as e: + let file = when defined(genode): + # stderr not available by default, use the LOG session + stdout + else: stderr + + # using `c_feof(file)` doesn't work + let fd = c_fileno(file) + if fd_is_valid(fd) != 0.cint: + let ex = getCurrentException() + let trace = ex.getStackTrace() + let msg = trace & "Error: unhandled exception: " & ex.msg & + " [" & $ex.name & "]\n" + file.write msg + # stderr.write "uncaught exception:" & e.msg + else: + # note(D20190117T013551): + # write to a logfile ($pid.log) if `--logerrorDir:mydir` is passed + discard + quit(1) + else: + fun() + +when not defined(nimscript): + {.emit:""" + NIM_EXTERNC bool fileDescriptorIsValid(int fd) { + return fcntl(fd, F_GETFD) != -1 || errno != EBADF; + } + """.} + + proc fileDescriptorIsValid(fd:cint): bool {.cdecl, importc.} + + proc writeToStdErrRobust(msg: string) {.exportc.} = + # using `c_feof(stderr)` doesn't give usable answer + let fd = c_fileno(stderr) + if fileDescriptorIsValid(fd): + stderr.write msg + else: + # note(D20190117T013551): + # write to a logfile ($pid.log) if `--logerrorDir:mydir` is passed + discard diff --git a/tests/exception/t9657.nim b/tests/exception/t9657.nim index ea93aff598a77..56bc573c8cc14 100644 --- a/tests/exception/t9657.nim +++ b/tests/exception/t9657.nim @@ -1,11 +1,15 @@ discard """ action: run exitcode: 1 - target: "c" + targets: "c cpp" disabled: "openbsd" disabled: "netbsd" """ -# todo: remove `target: "c"` workaround once #10343 is properly fixed + close stdmsg -const m = "exception!" -discard writeBuffer(stdmsg, cstring(m), m.len) +writeLine stdmsg, "exception!" + +when false: + # was there a 2nd issue/subtelty here? + const m = "exception!" + discard writeBuffer(stdmsg, cstring(m), m.len)