summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2017-01-20 17:08:11 +0100
committerAraq <rumpf_a@web.de>2017-01-20 17:08:11 +0100
commitcdebcf23d94939690ebdd08151984d926d9b566e (patch)
tree3e542060b3b9f1c250a32615382502ba5182f024 /lib/pure
parent64a7d2fd08c7f146260696e6c633420a95a3d4af (diff)
downloadNim-cdebcf23d94939690ebdd08151984d926d9b566e.tar.gz
new segfaults.nim stdlib module works on Windows
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/segfaults.nim42
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