From 6ee44597552ed5fafce020fe2e27961cc1fe699c Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Mon, 31 Oct 2022 23:50:28 +0800 Subject: [PATCH 01/15] fixes #20694; range check the parameter of the proc `quit` --- lib/system.nim | 98 ++++++++++++++++++++----------- lib/system/dyncalls.nim | 10 ++-- lib/system/excpt.nim | 16 ++--- lib/system/fatal.nim | 2 +- lib/system/gc.nim | 4 +- lib/system/gc2.nim | 2 +- lib/system/gc_common.nim | 4 +- lib/system/gc_hooks.nim | 4 +- lib/system/gc_ms.nim | 2 +- lib/system/memtracker.nim | 2 +- lib/system/mmdisp.nim | 2 +- lib/system/orc.nim | 4 +- lib/system/osalloc.nim | 2 +- lib/system/threadlocalstorage.nim | 2 +- tests/errmsgs/t20694.nim | 5 ++ 15 files changed, 97 insertions(+), 62 deletions(-) create mode 100644 tests/errmsgs/t20694.nim diff --git a/lib/system.nim b/lib/system.nim index 68645cea06eba..26927a31c1856 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1087,32 +1087,7 @@ proc align(address, alignment: int): int = result = (address + (alignment - 1)) and not (alignment - 1) when defined(nimNoQuit): - proc quit*(errorcode: int = QuitSuccess) = discard "ignoring quit" - ## Stops the program immediately with an exit code. - ## - ## Before stopping the program the "exit procedures" are called in the - ## opposite order they were added with `addExitProc `_. - ## - ## The proc `quit(QuitSuccess)` is called implicitly when your nim - ## program finishes without incident for platforms where this is the - ## expected behavior. A raised unhandled exception is - ## equivalent to calling `quit(QuitFailure)`. - ## - ## Note that this is a *runtime* call and using `quit` inside a macro won't - ## have any compile time effect. If you need to stop the compiler inside a - ## macro, use the `error `_ or `fatal - ## `_ pragmas. - ## - ## .. danger:: In almost all cases, in particular in library code, prefer - ## alternatives, e.g. `doAssert false` or raise a `Defect`. - ## `quit` bypasses regular control flow in particular `defer`, - ## `try`, `catch`, `finally` and `destructors`, and exceptions that may have been - ## raised by an `addExitProc` proc, as well as cleanup code in other threads. - ## It does *not* call the garbage collector to free all the memory, - ## unless an `addExitProc` proc calls `GC_fullCollect <#GC_fullCollect>`_. - -elif defined(nimdoc): - proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.} + proc rawQuit(errorcode: int = QuitSuccess) = discard "ignoring quit" elif defined(genode): import genode/env @@ -1122,18 +1097,15 @@ elif defined(genode): type GenodeEnv* = GenodeEnvPtr ## Opaque type representing Genode environment. - proc quit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, + proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "".} - proc quit*(errorcode: int = QuitSuccess) = - systemEnv.quit(errorcode) - elif defined(js) and defined(nodejs) and not defined(nimscript): - proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", + proc rawQuit(errorcode: int = QuitSuccess) {.magic: "Exit", importc: "process.exit", noreturn.} else: - proc quit*(errorcode: int = QuitSuccess) {. + proc rawQuit(errorcode: int = QuitSuccess) {. magic: "Exit", importc: "exit", header: "", noreturn.} @@ -2279,8 +2251,7 @@ when defined(js): include "system/jssys" include "system/reprjs" -proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} = - ## A shorthand for `echo(errormsg); quit(errorcode)`. +template printErrorMessage(errormsg: cstring) = when defined(nimscript) or defined(js) or (hostOS == "standalone"): echo errormsg else: @@ -2289,6 +2260,65 @@ proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} = else: cstderr.rawWrite(errormsg) cstderr.rawWrite("\n") + +when defined(nimNoQuit): + proc quit*(errorcode: int = QuitSuccess) = discard "ignoring quit" + ## Stops the program immediately with an exit code. + ## + ## Before stopping the program the "exit procedures" are called in the + ## opposite order they were added with `addExitProc `_. + ## + ## The proc `quit(QuitSuccess)` is called implicitly when your nim + ## program finishes without incident for platforms where this is the + ## expected behavior. A raised unhandled exception is + ## equivalent to calling `quit(QuitFailure)`. + ## + ## Note that this is a *runtime* call and using `quit` inside a macro won't + ## have any compile time effect. If you need to stop the compiler inside a + ## macro, use the `error `_ or `fatal + ## `_ pragmas. + ## + ## .. danger:: In almost all cases, in particular in library code, prefer + ## alternatives, e.g. `doAssert false` or raise a `Defect`. + ## `quit` bypasses regular control flow in particular `defer`, + ## `try`, `catch`, `finally` and `destructors`, and exceptions that may have been + ## raised by an `addExitProc` proc, as well as cleanup code in other threads. + ## It does *not* call the garbage collector to free all the memory, + ## unless an `addExitProc` proc calls `GC_fullCollect <#GC_fullCollect>`_. + +elif defined(nimdoc): + proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.} + +elif defined(genode): + proc quit*(errorcode: int = QuitSuccess) = + systemEnv.rawQuit(errorcode) + +elif defined(js) and defined(nodejs) and not defined(nimscript): + proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", + importc: "process.exit", noreturn.} + +else: + proc quit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = + when defined(posix): # posix uses low 8 bits + type exitCodeRange = int8 + else: # win32 uses low 32 bits + type exitCodeRange = int32 + let errorMsg = "forced to truncate exit code " & $errorcode & " to " & $(errorcode and high(exitCodeRange)) + if errorcode < low(exitCodeRange) or errorcode > high(exitCodeRange): + printErrorMessage errorMsg + rawQuit(errorcode) + +template sysAssert(cond: bool, msg: string) = + when defined(useSysAssert): + if not cond: + cstderr.rawWrite "[SYSASSERT] " + cstderr.rawWrite msg + cstderr.rawWrite "\n" + quit 1 + +proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} = + ## A shorthand for `echo(errormsg); quit(errorcode)`. + printErrorMessage(errormsg) quit(errorcode) {.pop.} # checks: off diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim index 36c2c5fe1a4cc..d5ebe3c19c913 100644 --- a/lib/system/dyncalls.nim +++ b/lib/system/dyncalls.nim @@ -47,14 +47,14 @@ proc nimLoadLibraryError(path: string) = copyMem(msg[msgIdx].addr, badExe.cstring, badExe.len) discard MessageBoxA(nil, msg[0].addr, nil, 0) cstderr.rawWrite("\n") - quit(1) + rawQuit(1) proc procAddrError(name: cstring) {.compilerproc, nonReloadable, hcrInline.} = # carefully written to avoid memory allocation: cstderr.rawWrite("could not import: ") cstderr.rawWrite(name) cstderr.rawWrite("\n") - quit(1) + rawQuit(1) # this code was inspired from Lua's source code: # Lua - An Extensible Extension Language @@ -180,19 +180,19 @@ elif defined(nintendoswitch) or defined(freertos) or defined(zephyr): proc nimUnloadLibrary(lib: LibHandle) = cstderr.rawWrite("nimUnLoadLibrary not implemented") cstderr.rawWrite("\n") - quit(1) + rawQuit(1) proc nimLoadLibrary(path: string): LibHandle = cstderr.rawWrite("nimLoadLibrary not implemented") cstderr.rawWrite("\n") - quit(1) + rawQuit(1) proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr = cstderr.rawWrite("nimGetProAddr not implemented") cstderr.rawWrite(name) cstderr.rawWrite("\n") - quit(1) + rawQuit(1) else: {.error: "no implementation for dyncalls".} diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index a71328c14c302..c76be554f51b7 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -415,7 +415,7 @@ proc nimLeaveFinally() {.compilerRtl.} = c_longjmp(excHandler.context, 1) else: reportUnhandledError(currException) - quit(1) + rawQuit(1) when gotoBasedExceptions: var nimInErrorMode {.threadvar.}: bool @@ -430,13 +430,13 @@ when gotoBasedExceptions: if nimInErrorMode and currException != nil: reportUnhandledError(currException) currException = nil - quit(1) + rawQuit(1) proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} = when defined(nimPanics): if e of Defect: reportUnhandledError(e) - quit(1) + rawQuit(1) if localRaiseHook != nil: if not localRaiseHook(e): return @@ -458,7 +458,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} = c_longjmp(excHandler.context, 1) else: reportUnhandledError(e) - quit(1) + rawQuit(1) proc raiseExceptionEx(e: sink(ref Exception), ename, procname, filename: cstring, line: int) {.compilerRtl, nodestroy.} = @@ -501,7 +501,7 @@ proc threadTrouble() = if currException != nil: reportUnhandledError(currException) except: discard - quit 1 + rawQuit 1 proc writeStackTrace() = when hasSomeStackTrace: @@ -544,7 +544,7 @@ proc callDepthLimitReached() {.noinline.} = "-d:nimCallDepthLimit= but really try to avoid deep " & "recursions instead.\n" showErrorMessage2(msg) - quit(1) + rawQuit(1) proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} = if framePtr == nil: @@ -597,7 +597,7 @@ when defined(cpp) and appType != "lib" and not gotoBasedExceptions and else: writeToStdErr msg & "\n" - quit 1 + rawQuit 1 when not defined(noSignalHandler) and not defined(useNimRtl): type Sighandler = proc (a: cint) {.noconv, benign.} @@ -651,7 +651,7 @@ when not defined(noSignalHandler) and not defined(useNimRtl): # also return the correct exit code to the shell. discard c_raise(sign) else: - quit(1) + rawQuit(1) var SIG_IGN {.importc: "SIG_IGN", header: "".}: Sighandler diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index c01787a326612..a55af2dc3989b 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -44,7 +44,7 @@ elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript): add(buf, name exceptn) add(buf, "]\n") cstderr.rawWrite buf - quit 1 + rawQuit 1 func sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} = sysFatal(exceptn, message, "") diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 4ab76c05e276d..b36822aadf785 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -161,7 +161,7 @@ template gcAssert(cond: bool, msg: string) = writeStackTrace() #var x: ptr int #echo x[] - quit 1 + rawQuit 1 proc addZCT(s: var CellSeq, c: PCell) {.noinline.} = if (c.refcount and ZctFlag) == 0: @@ -626,7 +626,7 @@ when logGC: if cycleCheckA[i] == c: return true if cycleCheckALen == len(cycleCheckA): gcAssert(false, "cycle detection overflow") - quit 1 + rawQuit 1 cycleCheckA[cycleCheckALen] = c inc cycleCheckALen diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim index 45d467051ef3c..0593b396e3ca5 100644 --- a/lib/system/gc2.nim +++ b/lib/system/gc2.nim @@ -129,7 +129,7 @@ template gcAssert(cond: bool, msg: string) = echo "[GCASSERT] ", msg GC_disable() writeStackTrace() - quit 1 + rawQuit 1 proc cellToUsr(cell: PCell): pointer {.inline.} = # convert object (=pointer to refcount) to pointer to userdata diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index ea8857ece8fa4..f5f4f164fed2a 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -472,7 +472,7 @@ proc nimRegisterGlobalMarker(markerProc: GlobalMarkerProc) {.compilerproc.} = inc globalMarkersLen else: cstderr.rawWrite("[GC] cannot register global variable; too many global variables") - quit 1 + rawQuit 1 proc nimRegisterThreadLocalMarker(markerProc: GlobalMarkerProc) {.compilerproc.} = if threadLocalMarkersLen <= high(threadLocalMarkers): @@ -480,4 +480,4 @@ proc nimRegisterThreadLocalMarker(markerProc: GlobalMarkerProc) {.compilerproc.} inc threadLocalMarkersLen else: cstderr.rawWrite("[GC] cannot register thread local variable; too many thread local variables") - quit 1 + rawQuit 1 diff --git a/lib/system/gc_hooks.nim b/lib/system/gc_hooks.nim index 70f02e6574a44..ace62eea0a13b 100644 --- a/lib/system/gc_hooks.nim +++ b/lib/system/gc_hooks.nim @@ -24,7 +24,7 @@ proc nimRegisterGlobalMarker(markerProc: GlobalMarkerProc) {.compilerproc.} = inc globalMarkersLen else: cstderr.rawWrite("[GC] cannot register global variable; too many global variables") - quit 1 + rawQuit 1 proc nimRegisterThreadLocalMarker(markerProc: GlobalMarkerProc) {.compilerproc.} = if threadLocalMarkersLen <= high(threadLocalMarkers): @@ -32,7 +32,7 @@ proc nimRegisterThreadLocalMarker(markerProc: GlobalMarkerProc) {.compilerproc.} inc threadLocalMarkersLen else: cstderr.rawWrite("[GC] cannot register thread local variable; too many thread local variables") - quit 1 + rawQuit 1 proc traverseGlobals*() = for i in 0..globalMarkersLen-1: diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index 0675b9f2eef6a..f91b37b941753 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -90,7 +90,7 @@ template gcAssert(cond: bool, msg: string) = if not cond: cstderr.rawWrite "[GCASSERT] " cstderr.rawWrite msg - quit 1 + rawQuit 1 proc cellToUsr(cell: PCell): pointer {.inline.} = # convert object (=pointer to refcount) to pointer to userdata diff --git a/lib/system/memtracker.nim b/lib/system/memtracker.nim index 9d2d7caeede45..289f4e02450dd 100644 --- a/lib/system/memtracker.nim +++ b/lib/system/memtracker.nim @@ -72,7 +72,7 @@ proc addEntry(entry: LogEntry) = cprintf("interesting %s:%ld %s\n", entry.file, entry.line, entry.op) let x = cast[proc() {.nimcall, tags: [], gcsafe, raises: [].}](writeStackTrace) x() - quit 1 + rawQuit 1 #if gLog.count > high(gLog.data): # gLogger(gLog) # gLog.count = 0 diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index e5038387fcdc0..26f2f0bbf0a9d 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -46,7 +46,7 @@ else: proc raiseOutOfMem() {.noinline.} = if outOfMemHook != nil: outOfMemHook() cstderr.rawWrite("out of memory\n") - quit(1) + rawQuit(1) when defined(boehmgc): include system / mm / boehm diff --git a/lib/system/orc.nim b/lib/system/orc.nim index 32c6b9adc49e5..83b983ee18c3d 100644 --- a/lib/system/orc.nim +++ b/lib/system/orc.nim @@ -114,7 +114,7 @@ template orcAssert(cond, msg) = when logOrc: if not cond: cfprintf(cstderr, "[Bug!] %s\n", msg) - quit 1 + rawQuit 1 when logOrc: proc strstr(s, sub: cstring): cstring {.header: "", importc.} @@ -143,7 +143,7 @@ proc unregisterCycle(s: Cell) = when false: if idx >= roots.len or idx < 0: cprintf("[Bug!] %ld\n", idx) - quit 1 + rawQuit 1 roots.d[idx] = roots.d[roots.len-1] roots.d[idx][0].rootIdx = idx+1 dec roots.len diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim index 39bf65d6c9485..4817059bee02a 100644 --- a/lib/system/osalloc.nim +++ b/lib/system/osalloc.nim @@ -189,7 +189,7 @@ elif defined(windows) and not defined(StandaloneHeapSize): when reallyOsDealloc: if virtualFree(p, 0, MEM_RELEASE) == 0: cprintf "virtualFree failing!" - quit 1 + rawQuit 1 #VirtualFree(p, size, MEM_DECOMMIT) elif hostOS == "standalone" or defined(StandaloneHeapSize): diff --git a/lib/system/threadlocalstorage.nim b/lib/system/threadlocalstorage.nim index 977f42e723825..e6ad9dca583ca 100644 --- a/lib/system/threadlocalstorage.nim +++ b/lib/system/threadlocalstorage.nim @@ -122,4 +122,4 @@ when not defined(useNimRtl): if nimThreadVarsSize() > sizeof(ThreadLocalStorage): c_fprintf(cstderr, """too large thread local storage size requested, use -d:\"nimTlsSize=X\" to setup even more or stop using unittest.nim""") - quit 1 + rawQuit 1 diff --git a/tests/errmsgs/t20694.nim b/tests/errmsgs/t20694.nim new file mode 100644 index 0000000000000..84c638036a11f --- /dev/null +++ b/tests/errmsgs/t20694.nim @@ -0,0 +1,5 @@ +discard """ + output: "forced to truncate exit code 4294967296 to 0" +""" +# bug #20694 +quit(0x100000000.int) \ No newline at end of file From aa00d2b9b3c7827d6394acf2be9fc359ec571cad Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 00:02:36 +0800 Subject: [PATCH 02/15] fixes --- lib/system.nim | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 26927a31c1856..e965fb258837a 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1109,14 +1109,6 @@ else: magic: "Exit", importc: "exit", header: "", noreturn.} -template sysAssert(cond: bool, msg: string) = - when defined(useSysAssert): - if not cond: - cstderr.rawWrite "[SYSASSERT] " - cstderr.rawWrite msg - cstderr.rawWrite "\n" - quit 1 - const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) when notJSnotNims and hostOS != "standalone" and hostOS != "any": @@ -2290,7 +2282,7 @@ elif defined(nimdoc): proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.} elif defined(genode): - proc quit*(errorcode: int = QuitSuccess) = + proc quit*(errorcode: int = QuitSuccess) {.inline.} = systemEnv.rawQuit(errorcode) elif defined(js) and defined(nodejs) and not defined(nimscript): From 05726c86f2667e5d7e69165376f816cc169c48c9 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 00:05:21 +0800 Subject: [PATCH 03/15] fixes --- lib/system.nim | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index e965fb258837a..431d6bc4eca3d 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1109,6 +1109,14 @@ else: magic: "Exit", importc: "exit", header: "", noreturn.} +template sysAssert(cond: bool, msg: string) = + when defined(useSysAssert): + if not cond: + cstderr.rawWrite "[SYSASSERT] " + cstderr.rawWrite msg + cstderr.rawWrite "\n" + quit 1 + const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) when notJSnotNims and hostOS != "standalone" and hostOS != "any": @@ -2282,7 +2290,7 @@ elif defined(nimdoc): proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.} elif defined(genode): - proc quit*(errorcode: int = QuitSuccess) {.inline.} = + proc quit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = systemEnv.rawQuit(errorcode) elif defined(js) and defined(nodejs) and not defined(nimscript): @@ -2300,14 +2308,6 @@ else: printErrorMessage errorMsg rawQuit(errorcode) -template sysAssert(cond: bool, msg: string) = - when defined(useSysAssert): - if not cond: - cstderr.rawWrite "[SYSASSERT] " - cstderr.rawWrite msg - cstderr.rawWrite "\n" - quit 1 - proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} = ## A shorthand for `echo(errormsg); quit(errorcode)`. printErrorMessage(errormsg) From 1fa959af474baac60541a51f42660e80bd03eeb3 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 10:00:44 +0800 Subject: [PATCH 04/15] fixes rawQuit --- lib/system.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 431d6bc4eca3d..7c7232f64b2a1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1115,7 +1115,7 @@ template sysAssert(cond: bool, msg: string) = cstderr.rawWrite "[SYSASSERT] " cstderr.rawWrite msg cstderr.rawWrite "\n" - quit 1 + rawQuit 1 const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) @@ -2300,9 +2300,9 @@ elif defined(js) and defined(nodejs) and not defined(nimscript): else: proc quit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = when defined(posix): # posix uses low 8 bits - type exitCodeRange = int8 + type ExitCodeRange = int8 else: # win32 uses low 32 bits - type exitCodeRange = int32 + type ExitCodeRange = int32 let errorMsg = "forced to truncate exit code " & $errorcode & " to " & $(errorcode and high(exitCodeRange)) if errorcode < low(exitCodeRange) or errorcode > high(exitCodeRange): printErrorMessage errorMsg From 8d8499d011f64f1beab00543192dc955d5ccae3d Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 10:01:54 +0800 Subject: [PATCH 05/15] typo --- lib/system.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 7c7232f64b2a1..24b5343d9fca3 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2303,8 +2303,8 @@ else: type ExitCodeRange = int8 else: # win32 uses low 32 bits type ExitCodeRange = int32 - let errorMsg = "forced to truncate exit code " & $errorcode & " to " & $(errorcode and high(exitCodeRange)) - if errorcode < low(exitCodeRange) or errorcode > high(exitCodeRange): + let errorMsg = "forced to truncate exit code " & $errorcode & " to " & $(errorcode and high(ExitCodeRange)) + if errorcode < low(ExitCodeRange) or errorcode > high(ExitCodeRange): printErrorMessage errorMsg rawQuit(errorcode) From 73dee3309068e9c9235b91ae2dc668f66fd20303 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 10:09:32 +0800 Subject: [PATCH 06/15] fixes more --- lib/system/arc.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/arc.nim b/lib/system/arc.nim index ccf9d44e27559..50dec241fe06c 100644 --- a/lib/system/arc.nim +++ b/lib/system/arc.nim @@ -154,7 +154,7 @@ proc nimRawDispose(p: pointer, alignment: int) {.compilerRtl.} = when defined(nimOwnedEnabled): if head(p).rc >= rcIncrement: cstderr.rawWrite "[FATAL] dangling references exist\n" - quit 1 + rawQuit 1 when defined(nimArcDebug): # we do NOT really free the memory here in order to reliably detect use-after-frees if freedCells.data == nil: init(freedCells) From c04c3e0267047d62cfc8d4c5d050f4a41f53c06c Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 10:25:59 +0800 Subject: [PATCH 07/15] fixes js --- lib/system/fatal.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index a55af2dc3989b..1d6860bbf3eb8 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -24,7 +24,7 @@ when hostOS == "standalone": rawoutput(message) panic(arg) -elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript): +elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript) and not defined(js): import ansi_c func name(t: typedesc): string {.magic: "TypeTrait".} From 99b5f6f135bbd38867f073fc9bf378d608f5fd09 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:12:19 +0800 Subject: [PATCH 08/15] fixes `sysFatal` --- lib/system.nim | 37 ++++++++----------------------------- lib/system/fatal.nim | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index bf3b3e96e4fbf..4dbf30d9ca09f 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1086,37 +1086,8 @@ proc align(address, alignment: int): int = else: result = (address + (alignment - 1)) and not (alignment - 1) -when defined(nimNoQuit): - proc rawQuit(errorcode: int = QuitSuccess) = discard "ignoring quit" - -elif defined(genode): - import genode/env - - var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr - - type GenodeEnv* = GenodeEnvPtr - ## Opaque type representing Genode environment. - - proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, - importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "".} - -elif defined(js) and defined(nodejs) and not defined(nimscript): - proc rawQuit(errorcode: int = QuitSuccess) {.magic: "Exit", - importc: "process.exit", noreturn.} - -else: - proc rawQuit(errorcode: int = QuitSuccess) {. - magic: "Exit", importc: "exit", header: "", noreturn.} -template sysAssert(cond: bool, msg: string) = - when defined(useSysAssert): - if not cond: - cstderr.rawWrite "[SYSASSERT] " - cstderr.rawWrite msg - cstderr.rawWrite "\n" - rawQuit 1 - const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) when notJSnotNims and hostOS != "standalone" and hostOS != "any": @@ -1617,6 +1588,14 @@ else: import system/fatal +template sysAssert(cond: bool, msg: string) = + when defined(useSysAssert): + if not cond: + cstderr.rawWrite "[SYSASSERT] " + cstderr.rawWrite msg + cstderr.rawWrite "\n" + rawQuit 1 + when not defined(nimscript): {.push stackTrace: off, profiler: off.} diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index 51cbbea3f98ee..b92fd73cd5526 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -9,6 +9,30 @@ {.push profiler: off.} + +when defined(nimNoQuit): + proc rawQuit*(errorcode: int = QuitSuccess) = discard "ignoring quit" + +elif defined(genode): + import genode/env + + var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr + + type GenodeEnv* = GenodeEnvPtr + ## Opaque type representing Genode environment. + + proc rawQuit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, + importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "".} + +elif defined(js) and defined(nodejs) and not defined(nimscript): + proc rawQuit*(errorcode: int = QuitSuccess) {.magic: "Exit", + importc: "process.exit", noreturn.} + +else: + proc rawQuit*(errorcode: int = QuitSuccess) {. + magic: "Exit", importc: "exit", header: "", noreturn.} + + when hostOS == "standalone": include "$projectpath/panicoverride" From 20ebe6fc029d0bc1b6a9e024f34d8c3836bd5ba1 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:18:11 +0800 Subject: [PATCH 09/15] fixes genode --- lib/system.nim | 6 +++++- lib/system/fatal.nim | 9 +++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 4dbf30d9ca09f..5403ff074178d 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1586,6 +1586,10 @@ when defined(nimHasExceptionsQuery): else: const gotoBasedExceptions = false +when defined(genode): + type GenodeEnv* = GenodeEnvPtr + ## Opaque type representing Genode environment. + import system/fatal template sysAssert(cond: bool, msg: string) = @@ -2276,7 +2280,7 @@ elif defined(nimdoc): elif defined(genode): proc quit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = - systemEnv.rawQuit(errorcode) + rawQuit(errorcode) elif defined(js) and defined(nodejs) and not defined(nimscript): proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index b92fd73cd5526..0949c1dbb02f0 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -18,12 +18,13 @@ elif defined(genode): var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr - type GenodeEnv* = GenodeEnvPtr - ## Opaque type representing Genode environment. - - proc rawQuit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, + proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "".} + proc rawQuit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = + systemEnv.rawQuit(errorcode) + + elif defined(js) and defined(nodejs) and not defined(nimscript): proc rawQuit*(errorcode: int = QuitSuccess) {.magic: "Exit", importc: "process.exit", noreturn.} From 9c39f61393326bb05de11655b94ee2292c78f46b Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:28:17 +0800 Subject: [PATCH 10/15] fixes --- lib/system.nim | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 5403ff074178d..8ed8ecfbb08a7 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1551,29 +1551,6 @@ when notJSnotNims: {.push stackTrace: off.} -when not defined(js) and hasThreadSupport and hostOS != "standalone": - import std/private/syslocks - include "system/threadlocalstorage" - -when not defined(js) and defined(nimV2): - type - DestructorProc = proc (p: pointer) {.nimcall, benign, raises: [].} - TNimTypeV2 {.compilerproc.} = object - destructor: pointer - size: int - align: int - name: cstring - traceImpl: pointer - typeInfoV1: pointer # for backwards compat, usually nil - flags: int - PNimTypeV2 = ptr TNimTypeV2 - -when notJSnotNims and defined(nimSeqsV2): - include "system/strs_v2" - include "system/seqs_v2" - -{.pop.} - when not defined(nimscript): proc writeStackTrace*() {.tags: [], gcsafe, raises: [].} ## Writes the current stack trace to `stderr`. This is only works @@ -1600,6 +1577,30 @@ template sysAssert(cond: bool, msg: string) = cstderr.rawWrite "\n" rawQuit 1 +when not defined(js) and hasThreadSupport and hostOS != "standalone": + import std/private/syslocks + include "system/threadlocalstorage" + +when not defined(js) and defined(nimV2): + type + DestructorProc = proc (p: pointer) {.nimcall, benign, raises: [].} + TNimTypeV2 {.compilerproc.} = object + destructor: pointer + size: int + align: int + name: cstring + traceImpl: pointer + typeInfoV1: pointer # for backwards compat, usually nil + flags: int + PNimTypeV2 = ptr TNimTypeV2 + +when notJSnotNims and defined(nimSeqsV2): + include "system/strs_v2" + include "system/seqs_v2" + +{.pop.} + + when not defined(nimscript): {.push stackTrace: off, profiler: off.} From ddf8877bc55e74292a0c41c7299c7ec0f791f79e Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 18:09:58 +0800 Subject: [PATCH 11/15] fixes --- lib/system.nim | 4 ++++ tests/errmsgs/t20694.nim | 1 + 2 files changed, 5 insertions(+) diff --git a/lib/system.nim b/lib/system.nim index 8ed8ecfbb08a7..d422e62206b5a 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1557,6 +1557,7 @@ when not defined(nimscript): ## for debug builds. Since it's usually used for debugging, this ## is proclaimed to have no IO effect! +{.pop.} when defined(nimHasExceptionsQuery): const gotoBasedExceptions = compileOption("exceptions", "goto") @@ -1564,6 +1565,7 @@ else: const gotoBasedExceptions = false when defined(genode): + import genode/env type GenodeEnv* = GenodeEnvPtr ## Opaque type representing Genode environment. @@ -1577,6 +1579,8 @@ template sysAssert(cond: bool, msg: string) = cstderr.rawWrite "\n" rawQuit 1 +{.push stackTrace: off.} + when not defined(js) and hasThreadSupport and hostOS != "standalone": import std/private/syslocks include "system/threadlocalstorage" diff --git a/tests/errmsgs/t20694.nim b/tests/errmsgs/t20694.nim index 84c638036a11f..ca51d41bac0c9 100644 --- a/tests/errmsgs/t20694.nim +++ b/tests/errmsgs/t20694.nim @@ -1,4 +1,5 @@ discard """ + disabled: i386 output: "forced to truncate exit code 4294967296 to 0" """ # bug #20694 From 6ce964cfe2dbb651e2b95d553f05224d6b37b2ee Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 18:12:10 +0800 Subject: [PATCH 12/15] fixes cstrings --- lib/system.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index d422e62206b5a..dc3113ac51bf0 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2245,14 +2245,14 @@ when defined(js): include "system/jssys" include "system/reprjs" -template printErrorMessage(errormsg: cstring) = +template printErrorMessage(errormsg: string) = when defined(nimscript) or defined(js) or (hostOS == "standalone"): echo errormsg else: when nimvm: echo errormsg else: - cstderr.rawWrite(errormsg) + cstderr.rawWrite(errormsg.cstring) cstderr.rawWrite("\n") when defined(nimNoQuit): From 53b6e62b8c4664f7bc6567afaa39592ecb4c28b5 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 1 Nov 2022 19:18:29 +0800 Subject: [PATCH 13/15] fixes windows --- lib/genode/alloc.nim | 2 +- lib/system.nim | 2 +- lib/system/fatal.nim | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/genode/alloc.nim b/lib/genode/alloc.nim index efc25ac57da4b..24fb9954efada 100644 --- a/lib/genode/alloc.nim +++ b/lib/genode/alloc.nim @@ -111,7 +111,7 @@ proc osDeallocPages(p: pointer; size: int) = if m.attachment == p: if m.size != size: echo "cannot partially detach dataspace" - quit -1 + rawQuit -1 runtimeEnv.detachAddress m.attachment runtimeEnv.freeDataspace m.ds m[] = Map() diff --git a/lib/system.nim b/lib/system.nim index dc3113ac51bf0..49336ada366dd 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2677,7 +2677,7 @@ when defined(genode): proc nim_component_construct(env: GenodeEnv) {.exportc.} = ## Procedure called during `Component::construct` by the loader. if componentConstructHook.isNil: - env.quit(programResult) + env.rawQuit(programResult) # No native Genode application initialization, # exit as would POSIX. else: diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index 0949c1dbb02f0..1f4ac473231b9 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -18,7 +18,7 @@ elif defined(genode): var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr - proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, + proc rawQuit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "".} proc rawQuit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = From f47d2c8148ea39440a929cd66e0c8bb414d86192 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 1 Nov 2022 19:51:23 +0800 Subject: [PATCH 14/15] another fix --- lib/std/assertions.nim | 5 +++-- lib/system.nim | 13 +++++++------ lib/system/fatal.nim | 26 +++++++++++++------------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/std/assertions.nim b/lib/std/assertions.nim index a39aee6c80038..fb79333fbf3c3 100644 --- a/lib/std/assertions.nim +++ b/lib/std/assertions.nim @@ -9,8 +9,6 @@ ## This module implements assertion handling. -import system/fatal - import std/private/miscdollars # --------------------------------------------------------------------------- # helpers @@ -28,6 +26,9 @@ proc `$`(info: InstantiationInfo): string = when not defined(nimHasSinkInference): {.pragma: nosinks.} +template sysFatal(exc, msg) = + raise newException(exc, msg) + proc raiseAssert*(msg: string) {.noinline, noreturn, nosinks.} = ## Raises an `AssertionDefect` with `msg`. sysFatal(AssertionDefect, msg) diff --git a/lib/system.nim b/lib/system.nim index 49336ada366dd..0b6cb1a7bf75e 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1569,7 +1569,7 @@ when defined(genode): type GenodeEnv* = GenodeEnvPtr ## Opaque type representing Genode environment. -import system/fatal +include system/fatal template sysAssert(cond: bool, msg: string) = when defined(useSysAssert): @@ -1616,6 +1616,12 @@ when not defined(nimscript): when defined(nimV2): include system/arc +template newException*(exceptn: typedesc, message: string; + parentException: ref Exception = nil): untyped = + ## Creates an exception object of type `exceptn` and sets its `msg` field + ## to `message`. Returns the new exception object. + (ref exceptn)(msg: message, parent: parentException) + when not defined(nimPreviewSlimSystem): {.deprecated: "assertions is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/assertions`".} import std/assertions @@ -1823,11 +1829,6 @@ proc debugEcho*(x: varargs[typed, `$`]) {.magic: "Echo", noSideEffect, ## for debugging routines marked as `noSideEffect ## `_. -template newException*(exceptn: typedesc, message: string; - parentException: ref Exception = nil): untyped = - ## Creates an exception object of type `exceptn` and sets its `msg` field - ## to `message`. Returns the new exception object. - (ref exceptn)(msg: message, parent: parentException) when hostOS == "standalone" and defined(nogc): proc nimToCStringConv(s: NimString): cstring {.compilerproc, inline.} = diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim index 1f4ac473231b9..6c74dd5fcf2e1 100644 --- a/lib/system/fatal.nim +++ b/lib/system/fatal.nim @@ -7,40 +7,40 @@ # distribution, for details about the copyright. # -{.push profiler: off.} - when defined(nimNoQuit): - proc rawQuit*(errorcode: int = QuitSuccess) = discard "ignoring quit" + proc rawQuit(errorcode: int = QuitSuccess) = discard "ignoring quit" elif defined(genode): import genode/env var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr - proc rawQuit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, + proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "".} - proc rawQuit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = + proc rawQuit(errorcode: int = QuitSuccess) {.inline, noreturn.} = systemEnv.rawQuit(errorcode) elif defined(js) and defined(nodejs) and not defined(nimscript): - proc rawQuit*(errorcode: int = QuitSuccess) {.magic: "Exit", + proc rawQuit(errorcode: int = QuitSuccess) {.magic: "Exit", importc: "process.exit", noreturn.} else: - proc rawQuit*(errorcode: int = QuitSuccess) {. + proc rawQuit(errorcode: int = QuitSuccess) {. magic: "Exit", importc: "exit", header: "", noreturn.} +{.push profiler: off.} + when hostOS == "standalone": include "$projectpath/panicoverride" - func sysFatal*(exceptn: typedesc, message: string) {.inline.} = + func sysFatal(exceptn: typedesc, message: string) {.inline.} = panic(message) - func sysFatal*(exceptn: typedesc, message, arg: string) {.inline.} = + func sysFatal(exceptn: typedesc, message, arg: string) {.inline.} = rawoutput(message) panic(arg) @@ -49,7 +49,7 @@ elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript): func name(t: typedesc): string {.magic: "TypeTrait".} - func sysFatal*(exceptn: typedesc, message, arg: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc, message, arg: string) {.inline, noreturn.} = when nimvm: # TODO when doAssertRaises works in CT, add a test for it raise (ref exceptn)(msg: message & arg) @@ -66,14 +66,14 @@ elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript): cstderr.rawWrite buf rawQuit 1 - func sysFatal*(exceptn: typedesc, message: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} = sysFatal(exceptn, message, "") else: - func sysFatal*(exceptn: typedesc, message: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} = raise (ref exceptn)(msg: message) - func sysFatal*(exceptn: typedesc, message, arg: string) {.inline, noreturn.} = + func sysFatal(exceptn: typedesc, message, arg: string) {.inline, noreturn.} = raise (ref exceptn)(msg: message & arg) {.pop.} From ed638fc9d55a50d907b561e2f9c0ae84fda88546 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 1 Nov 2022 20:46:07 +0800 Subject: [PATCH 15/15] next try --- lib/std/assertions.nim | 5 +---- tests/assert/tassert_c.nim | 2 +- tests/errmsgs/t20694.nim | 1 + tests/errmsgs/t9768.nim | 9 +++++---- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/std/assertions.nim b/lib/std/assertions.nim index fb79333fbf3c3..03bab1b1b014d 100644 --- a/lib/std/assertions.nim +++ b/lib/std/assertions.nim @@ -26,12 +26,9 @@ proc `$`(info: InstantiationInfo): string = when not defined(nimHasSinkInference): {.pragma: nosinks.} -template sysFatal(exc, msg) = - raise newException(exc, msg) - proc raiseAssert*(msg: string) {.noinline, noreturn, nosinks.} = ## Raises an `AssertionDefect` with `msg`. - sysFatal(AssertionDefect, msg) + raise newException(AssertionDefect, msg) proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} = ## Raises an `AssertionDefect` with `msg`, but this is hidden diff --git a/tests/assert/tassert_c.nim b/tests/assert/tassert_c.nim index 5c8f529adf44a..110a9aabf6d14 100644 --- a/tests/assert/tassert_c.nim +++ b/tests/assert/tassert_c.nim @@ -8,7 +8,7 @@ tassert_c.nim(35) tassert_c tassert_c.nim(34) foo assertions.nim(*) failedAssertImpl assertions.nim(*) raiseAssert -fatal.nim(*) sysFatal""" +""" proc tmatch(x, p: string): bool = var i = 0 diff --git a/tests/errmsgs/t20694.nim b/tests/errmsgs/t20694.nim index ca51d41bac0c9..93df316ee13fa 100644 --- a/tests/errmsgs/t20694.nim +++ b/tests/errmsgs/t20694.nim @@ -1,4 +1,5 @@ discard """ + joinable: false disabled: i386 output: "forced to truncate exit code 4294967296 to 0" """ diff --git a/tests/errmsgs/t9768.nim b/tests/errmsgs/t9768.nim index b72a158c7573b..94def90f0726b 100644 --- a/tests/errmsgs/t9768.nim +++ b/tests/errmsgs/t9768.nim @@ -1,10 +1,10 @@ discard """ - errormsg: "unhandled exception:" - file: "system/fatal.nim" + errormsg: "unhandled exception: t9768.nim(24, 12) `a < 4` [AssertionDefect]" + file: "std/assertions.nim" nimout: ''' stack trace: (most recent call last) -t9768.nim(28, 33) main -t9768.nim(23, 11) foo1 +t9768.nim(29, 33) main +t9768.nim(24, 11) foo1 ''' """ @@ -17,6 +17,7 @@ t9768.nim(23, 11) foo1 + ## line 20 proc foo1(a: int): auto =