new segfaults.nim stdlib module works on Windows
This commit is contained in:
parent
64a7d2fd08
commit
cdebcf23d9
3 changed files with 48 additions and 5 deletions
|
|
@ -10,6 +10,8 @@
|
||||||
## This modules registers a signal handler that turns access violations /
|
## This modules registers a signal handler that turns access violations /
|
||||||
## segfaults into a ``NilAccessError`` exception. To be able to catch
|
## segfaults into a ``NilAccessError`` exception. To be able to catch
|
||||||
## a NilAccessError all you have to do is to import this module.
|
## a NilAccessError all you have to do is to import this module.
|
||||||
|
##
|
||||||
|
## Tested on these OSes: Linux, Windows, OSX
|
||||||
|
|
||||||
type
|
type
|
||||||
NilAccessError* = object of SystemError ## \
|
NilAccessError* = object of SystemError ## \
|
||||||
|
|
@ -18,17 +20,49 @@ type
|
||||||
# do allocate memory upfront:
|
# do allocate memory upfront:
|
||||||
var se: ref NilAccessError
|
var se: ref NilAccessError
|
||||||
new(se)
|
new(se)
|
||||||
|
se.name = "NilAccessError"
|
||||||
se.msg = ""
|
se.msg = ""
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
include "$lib/system/ansi_c"
|
include "$lib/system/ansi_c"
|
||||||
|
|
||||||
|
import winlean
|
||||||
|
|
||||||
|
const
|
||||||
|
EXCEPTION_ACCESS_VIOLATION = DWORD(0xc0000005)
|
||||||
|
EXCEPTION_CONTINUE_SEARCH = Long(0)
|
||||||
|
|
||||||
|
type
|
||||||
|
PEXCEPTION_RECORD = ptr object
|
||||||
|
exceptionCode: DWORD # other fields left out
|
||||||
|
|
||||||
|
PEXCEPTION_POINTERS = ptr object
|
||||||
|
exceptionRecord: PEXCEPTION_RECORD
|
||||||
|
contextRecord: pointer
|
||||||
|
|
||||||
|
VectoredHandler = proc (p: PEXCEPTION_POINTERS): LONG {.stdcall.}
|
||||||
|
proc addVectoredExceptionHandler(firstHandler: ULONG,
|
||||||
|
handler: VectoredHandler): pointer {.
|
||||||
|
importc: "AddVectoredExceptionHandler", stdcall, dynlib: "kernel32.dll"}
|
||||||
|
|
||||||
{.push stackTrace: off.}
|
{.push stackTrace: off.}
|
||||||
proc segfaultHandler(sig: cint) {.noconv.} =
|
proc segfaultHandler(p: PEXCEPTION_POINTERS): LONG {.stdcall.} =
|
||||||
{.gcsafe.}:
|
if p.exceptionRecord.exceptionCode == EXCEPTION_ACCESS_VIOLATION:
|
||||||
raise se
|
{.gcsafe.}:
|
||||||
|
raise se
|
||||||
|
else:
|
||||||
|
result = EXCEPTION_CONTINUE_SEARCH
|
||||||
{.pop.}
|
{.pop.}
|
||||||
c_signal(SIGSEGV, segfaultHandler)
|
|
||||||
|
discard addVectoredExceptionHandler(0, segfaultHandler)
|
||||||
|
|
||||||
|
when false:
|
||||||
|
{.push stackTrace: off.}
|
||||||
|
proc segfaultHandler(sig: cint) {.noconv.} =
|
||||||
|
{.gcsafe.}:
|
||||||
|
rawRaise se
|
||||||
|
{.pop.}
|
||||||
|
c_signal(SIGSEGV, segfaultHandler)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import posix
|
import posix
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,12 @@ proc quitOrDebug() {.inline.} =
|
||||||
else:
|
else:
|
||||||
endbStep() # call the debugger
|
endbStep() # call the debugger
|
||||||
|
|
||||||
|
when false:
|
||||||
|
proc rawRaise*(e: ref Exception) =
|
||||||
|
## undocumented. Do not use.
|
||||||
|
pushCurrentException(e)
|
||||||
|
c_longjmp(excHandler.context, 1)
|
||||||
|
|
||||||
proc raiseExceptionAux(e: ref Exception) =
|
proc raiseExceptionAux(e: ref Exception) =
|
||||||
if localRaiseHook != nil:
|
if localRaiseHook != nil:
|
||||||
if not localRaiseHook(e): return
|
if not localRaiseHook(e): return
|
||||||
|
|
@ -371,5 +377,4 @@ when not defined(noSignalHandler):
|
||||||
proc setControlCHook(hook: proc () {.noconv.} not nil) =
|
proc setControlCHook(hook: proc () {.noconv.} not nil) =
|
||||||
# ugly cast, but should work on all architectures:
|
# ugly cast, but should work on all architectures:
|
||||||
type SignalHandler = proc (sign: cint) {.noconv, benign.}
|
type SignalHandler = proc (sign: cint) {.noconv, benign.}
|
||||||
{.deprecated: [TSignalHandler: SignalHandler].}
|
|
||||||
c_signal(SIGINT, cast[SignalHandler](hook))
|
c_signal(SIGINT, cast[SignalHandler](hook))
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ proc main =
|
||||||
try:
|
try:
|
||||||
var x: ptr int
|
var x: ptr int
|
||||||
echo x[]
|
echo x[]
|
||||||
|
try:
|
||||||
|
raise newException(ValueError, "not a crash")
|
||||||
|
except ValueError:
|
||||||
|
discard
|
||||||
except NilAccessError:
|
except NilAccessError:
|
||||||
echo "caught a crash!"
|
echo "caught a crash!"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue