diff options
author | Araq <rumpf_a@web.de> | 2017-01-20 17:08:11 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2017-01-20 17:08:11 +0100 |
commit | cdebcf23d94939690ebdd08151984d926d9b566e (patch) | |
tree | 3e542060b3b9f1c250a32615382502ba5182f024 /lib | |
parent | 64a7d2fd08c7f146260696e6c633420a95a3d4af (diff) | |
download | Nim-cdebcf23d94939690ebdd08151984d926d9b566e.tar.gz |
new segfaults.nim stdlib module works on Windows
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/segfaults.nim | 42 | ||||
-rw-r--r-- | lib/system/excpt.nim | 7 |
2 files changed, 44 insertions, 5 deletions
diff --git a/lib/pure/segfaults.nim b/lib/pure/segfaults.nim index 3c3b59449..c53abb4aa 100644 --- a/lib/pure/segfaults.nim +++ b/lib/pure/segfaults.nim @@ -10,6 +10,8 @@ ## 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. +## +## Tested on these OSes: Linux, Windows, OSX type NilAccessError* = object of SystemError ## \ @@ -18,17 +20,49 @@ type # do allocate memory upfront: var se: ref NilAccessError new(se) +se.name = "NilAccessError" se.msg = "" when defined(windows): 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.} - proc segfaultHandler(sig: cint) {.noconv.} = - {.gcsafe.}: - raise se + proc segfaultHandler(p: PEXCEPTION_POINTERS): LONG {.stdcall.} = + if p.exceptionRecord.exceptionCode == EXCEPTION_ACCESS_VIOLATION: + {.gcsafe.}: + raise se + else: + result = EXCEPTION_CONTINUE_SEARCH {.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: import posix diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index d00ab64b1..b16590c92 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -212,6 +212,12 @@ proc quitOrDebug() {.inline.} = else: 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) = if localRaiseHook != nil: if not localRaiseHook(e): return @@ -371,5 +377,4 @@ when not defined(noSignalHandler): proc setControlCHook(hook: proc () {.noconv.} not nil) = # ugly cast, but should work on all architectures: type SignalHandler = proc (sign: cint) {.noconv, benign.} - {.deprecated: [TSignalHandler: SignalHandler].} c_signal(SIGINT, cast[SignalHandler](hook)) |