mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-18 23:11:36 +00:00
system/excpt: let the OS handle termination on signal (#16712)
This commit is contained in:
@@ -159,6 +159,14 @@ provided by the operating system.
|
||||
`ValueError` when the real command line is not available. `parseopt` was
|
||||
previously excluded from `prelude` for JS, as it could not be imported.
|
||||
|
||||
- On POSIX systems, the default signal handlers used for Nim programs (it's
|
||||
used for printing the stacktrace on fatal signals) will now re-raise the
|
||||
signal for the OS default handlers to handle.
|
||||
|
||||
This lets the OS perform its default actions, which might include core
|
||||
dumping (on select signals) and notifying the parent process about the cause
|
||||
of termination.
|
||||
|
||||
## Language changes
|
||||
|
||||
- `nimscript` now handles `except Exception as e`.
|
||||
|
||||
@@ -40,6 +40,7 @@ else:
|
||||
C_JmpBuf* {.importc: "jmp_buf", header: "<setjmp.h>".} = object
|
||||
|
||||
|
||||
type CSighandlerT = proc (a: cint) {.noconv.}
|
||||
when defined(windows):
|
||||
const
|
||||
SIGABRT* = cint(22)
|
||||
@@ -48,6 +49,7 @@ when defined(windows):
|
||||
SIGINT* = cint(2)
|
||||
SIGSEGV* = cint(11)
|
||||
SIGTERM = cint(15)
|
||||
SIG_DFL* = cast[CSighandlerT](0)
|
||||
elif defined(macosx) or defined(linux) or defined(freebsd) or
|
||||
defined(openbsd) or defined(netbsd) or defined(solaris) or
|
||||
defined(dragonfly) or defined(nintendoswitch) or defined(genode) or
|
||||
@@ -60,6 +62,7 @@ elif defined(macosx) or defined(linux) or defined(freebsd) or
|
||||
SIGSEGV* = cint(11)
|
||||
SIGTERM* = cint(15)
|
||||
SIGPIPE* = cint(13)
|
||||
SIG_DFL* = cast[CSighandlerT](0)
|
||||
elif defined(haiku):
|
||||
const
|
||||
SIGABRT* = cint(6)
|
||||
@@ -69,6 +72,7 @@ elif defined(haiku):
|
||||
SIGSEGV* = cint(11)
|
||||
SIGTERM* = cint(15)
|
||||
SIGPIPE* = cint(7)
|
||||
SIG_DFL* = cast[CSighandlerT](0)
|
||||
else:
|
||||
when NoFakeVars:
|
||||
{.error: "SIGABRT not ported to your platform".}
|
||||
@@ -79,6 +83,7 @@ else:
|
||||
SIGABRT* {.importc: "SIGABRT", nodecl.}: cint
|
||||
SIGFPE* {.importc: "SIGFPE", nodecl.}: cint
|
||||
SIGILL* {.importc: "SIGILL", nodecl.}: cint
|
||||
SIG_DFL* {.importc: "SIG_DFL", nodecl.}: CSighandlerT
|
||||
when defined(macosx) or defined(linux):
|
||||
var SIGPIPE* {.importc: "SIGPIPE", nodecl.}: cint
|
||||
|
||||
@@ -105,9 +110,9 @@ else:
|
||||
proc c_setjmp*(jmpb: C_JmpBuf): cint {.
|
||||
header: "<setjmp.h>", importc: "setjmp".}
|
||||
|
||||
type CSighandlerT = proc (a: cint) {.noconv.}
|
||||
proc c_signal*(sign: cint, handler: proc (a: cint) {.noconv.}): CSighandlerT {.
|
||||
proc c_signal*(sign: cint, handler: CSighandlerT): CSighandlerT {.
|
||||
importc: "signal", header: "<signal.h>", discardable.}
|
||||
proc c_raise*(sign: cint): cint {.importc: "raise", header: "<signal.h>".}
|
||||
|
||||
type
|
||||
CFile {.importc: "FILE", header: "<stdio.h>",
|
||||
|
||||
@@ -643,7 +643,17 @@ when not defined(noSignalHandler) and not defined(useNimRtl):
|
||||
# unless there's a good reason to use cstring in signal handler to avoid
|
||||
# using gc?
|
||||
showErrorMessage(msg, msg.len)
|
||||
quit(1) # always quit when SIGABRT
|
||||
|
||||
when defined(posix):
|
||||
# reset the signal handler to OS default
|
||||
c_signal(sign, SIG_DFL)
|
||||
|
||||
# re-raise the signal, which will arrive once this handler exit.
|
||||
# this lets the OS perform actions like core dumping and will
|
||||
# also return the correct exit code to the shell.
|
||||
discard c_raise(sign)
|
||||
else:
|
||||
quit(1)
|
||||
|
||||
proc registerSignalHandler() =
|
||||
c_signal(SIGINT, signalHandler)
|
||||
|
||||
20
tests/system/tsigexitcode.nim
Normal file
20
tests/system/tsigexitcode.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
joinable: false
|
||||
disabled: windows
|
||||
"""
|
||||
|
||||
import os, osproc, posix, strutils
|
||||
|
||||
proc main() =
|
||||
if paramCount() > 0:
|
||||
let signal = cint parseInt paramStr(1)
|
||||
discard posix.raise(signal)
|
||||
else:
|
||||
# synchronize this list with lib/system/except.nim:registerSignalHandler()
|
||||
let fatalSigs = [SIGINT, SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS,
|
||||
SIGPIPE]
|
||||
for s in fatalSigs:
|
||||
let (_, exitCode) = execCmdEx(quoteShellCommand [getAppFilename(), $s])
|
||||
doAssert exitCode == 128 + s, "mismatched exit code for signal " & $s
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user