From 7ff80cc8b2ec57b5797b3cf7d24d3b965ee2908a Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 20 Jan 2017 12:40:47 +0100 Subject: [PATCH] first implementation of segfaults stdlib module --- lib/pure/segfaults.nim | 54 +++++++++++++++++++++++++++++++++++++ tests/stdlib/tsegfaults.nim | 25 +++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 lib/pure/segfaults.nim create mode 100644 tests/stdlib/tsegfaults.nim diff --git a/lib/pure/segfaults.nim b/lib/pure/segfaults.nim new file mode 100644 index 0000000000..3c3b594492 --- /dev/null +++ b/lib/pure/segfaults.nim @@ -0,0 +1,54 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2017 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This modules registers a signal handler that turns access violations / +## segfaults into a ``NilAccessError`` exception. To be able to catch +## a NilAccessError all you have to do is to import this module. + +type + NilAccessError* = object of SystemError ## \ + ## Raised on dereferences of ``nil`` pointers. + +# do allocate memory upfront: +var se: ref NilAccessError +new(se) +se.msg = "" + +when defined(windows): + include "$lib/system/ansi_c" + + {.push stackTrace: off.} + proc segfaultHandler(sig: cint) {.noconv.} = + {.gcsafe.}: + raise se + {.pop.} + c_signal(SIGSEGV, segfaultHandler) + +else: + import posix + + var sa: Sigaction + + var SEGV_MAPERR {.importc, header: "".}: cint + + {.push stackTrace: off.} + proc segfaultHandler(sig: cint, y: var SigInfo, z: pointer) {.noconv.} = + if y.si_code == SEGV_MAPERR: + {.gcsafe.}: + raise se + else: + quit(1) + {.pop.} + + discard sigemptyset(sa.sa_mask) + + sa.sa_sigaction = segfaultHandler + sa.sa_flags = SA_SIGINFO or SA_NODEFER + + discard sigaction(SIGSEGV, sa) diff --git a/tests/stdlib/tsegfaults.nim b/tests/stdlib/tsegfaults.nim new file mode 100644 index 0000000000..1e63ba6600 --- /dev/null +++ b/tests/stdlib/tsegfaults.nim @@ -0,0 +1,25 @@ +discard """ + output: '''caught a crash! +caught a crash! +caught a crash! +caught a crash! +caught a crash! +caught a crash! +caught a crash! +caught a crash! +caught a crash! +caught a crash! +caught a crash!''' +""" + +import segfaults + +proc main = + try: + var x: ptr int + echo x[] + except NilAccessError: + echo "caught a crash!" + +for i in 0..10: + main()