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/pure | |
parent | 64a7d2fd08c7f146260696e6c633420a95a3d4af (diff) | |
download | Nim-cdebcf23d94939690ebdd08151984d926d9b566e.tar.gz |
new segfaults.nim stdlib module works on Windows
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/segfaults.nim | 42 |
1 files changed, 38 insertions, 4 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 |