summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-01-27 19:29:41 +0100
committerAndreas Rumpf <rumpf_a@web.de>2017-01-27 19:29:41 +0100
commit0e16d43196efdf901f359744c24636ab2b18f325 (patch)
treebec83e441dced198e58ffd968215b5396ef0371b
parent68617adb91ecae00725523ae6bf2833fe6c07bd1 (diff)
parent1bf78618fea5bd57b0b6ab2dbadd40e1d914b710 (diff)
downloadNim-0e16d43196efdf901f359744c24636ab2b18f325.tar.gz
Merge branch 'cheatfate-fix5290' into devel
-rw-r--r--lib/pure/asyncdispatch.nim13
-rw-r--r--lib/pure/ioselects/ioselectors_epoll.nim52
-rw-r--r--lib/pure/ioselects/ioselectors_kqueue.nim21
-rw-r--r--lib/pure/ioselects/ioselectors_poll.nim10
-rw-r--r--lib/pure/ioselects/ioselectors_select.nim28
-rw-r--r--lib/upcoming/asyncdispatch.nim57
6 files changed, 99 insertions, 82 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index b72596060..6fb460e25 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -871,7 +871,9 @@ when defined(windows) or defined(nimdoc):
         if unregisterWait(pcd.waitFd) == 0:
           let err = osLastError()
           if err.int32 != ERROR_IO_PENDING:
-            raiseOSError(osLastError())
+            deallocShared(cast[pointer](pcd))
+            discard wsaCloseEvent(hEvent)
+            raiseOSError(err)
         if cb(fd):
           # callback returned `true`, so we free all allocated resources
           deallocShared(cast[pointer](pcd))
@@ -895,9 +897,10 @@ when defined(windows) or defined(nimdoc):
                                     cast[WAITORTIMERCALLBACK](waitableCallback),
                                        cast[pointer](pcd), INFINITE, flags):
               # pcd.ovl will be unrefed in poll()
+              let err = osLastError()
               discard wsaCloseEvent(hEvent)
               deallocShared(cast[pointer](pcd))
-              raiseOSError(osLastError())
+              raiseOSError(err)
             else:
               # we incref `pcd.ovl` and `protect` callback one more time,
               # because it will be unrefed and disposed in `poll()` after
@@ -912,19 +915,21 @@ when defined(windows) or defined(nimdoc):
     # This is main part of `hacky way` is using WSAEventSelect, so `hEvent`
     # will be signaled when appropriate `mask` events will be triggered.
     if wsaEventSelect(fd.SocketHandle, hEvent, mask) != 0:
+      let err = osLastError()
       GC_unref(ol)
       deallocShared(cast[pointer](pcd))
       discard wsaCloseEvent(hEvent)
-      raiseOSError(osLastError())
+      raiseOSError(err)
 
     pcd.ovl = ol
     if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
                                     cast[WAITORTIMERCALLBACK](waitableCallback),
                                        cast[pointer](pcd), INFINITE, flags):
+      let err = osLastError()
       GC_unref(ol)
       deallocShared(cast[pointer](pcd))
       discard wsaCloseEvent(hEvent)
-      raiseOSError(osLastError())
+      raiseOSError(err)
     p.handles.incl(fd)
 
   proc addRead*(fd: AsyncFD, cb: Callback) =
diff --git a/lib/pure/ioselects/ioselectors_epoll.nim b/lib/pure/ioselects/ioselectors_epoll.nim
index cb555f001..f8feb7361 100644
--- a/lib/pure/ioselects/ioselectors_epoll.nim
+++ b/lib/pure/ioselects/ioselectors_epoll.nim
@@ -131,11 +131,12 @@ proc newSelector*[T](): Selector[T] =
     result.fds = newSeq[SelectorKey[T]](maxFD)
 
 proc close*[T](s: Selector[T]) =
-  if posix.close(s.epollFD) != 0:
-    raiseIOSelectorsError(osLastError())
+  let res = posix.close(s.epollFD)
   when hasThreadSupport:
     deallocSharedArray(s.fds)
     deallocShared(cast[pointer](s))
+  if res != 0:
+    raiseIOSelectorsError(osLastError())
 
 template clearKey[T](key: ptr SelectorKey[T]) =
   var empty: T
@@ -157,9 +158,10 @@ proc setEvent*(ev: SelectEvent) =
     raiseIOSelectorsError(osLastError())
 
 proc close*(ev: SelectEvent) =
-  if posix.close(ev.efd) == -1:
-    raiseIOSelectorsError(osLastError())
+  let res = posix.close(ev.efd)
   deallocShared(cast[pointer](ev))
+  if res != 0:
+    raiseIOSelectorsError(osLastError())
 
 template checkFd(s, f) =
   if f >= s.maxFD:
@@ -176,7 +178,7 @@ proc registerHandle*[T](s: Selector[T], fd: SocketHandle,
     epv.data.u64 = fdi.uint
     if Event.Read in events: epv.events = epv.events or EPOLLIN
     if Event.Write in events: epv.events = epv.events or EPOLLOUT
-    if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
+    if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) != 0:
       raiseIOSelectorsError(osLastError())
     inc(s.count)
 
@@ -196,15 +198,15 @@ proc updateHandle*[T](s: Selector[T], fd: SocketHandle, events: set[Event]) =
     if Event.Write in events: epv.events = epv.events or EPOLLOUT
 
     if pkey.events == {}:
-      if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
+      if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) != 0:
         raiseIOSelectorsError(osLastError())
       inc(s.count)
     else:
       if events != {}:
-        if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fdi.cint, addr epv) == -1:
+        if epoll_ctl(s.epollFD, EPOLL_CTL_MOD, fdi.cint, addr epv) != 0:
           raiseIOSelectorsError(osLastError())
       else:
-        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
           raiseIOSelectorsError(osLastError())
         dec(s.count)
     pkey.events = events
@@ -219,20 +221,20 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
     when not defined(android):
       if pkey.events * {Event.Read, Event.Write} != {}:
         var epv = epoll_event()
-        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
           raiseIOSelectorsError(osLastError())
         dec(s.count)
       elif Event.Timer in pkey.events:
         if Event.Finished notin pkey.events:
           var epv = epoll_event()
-          if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+          if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
             raiseIOSelectorsError(osLastError())
           dec(s.count)
-        if posix.close(cint(fdi)) == -1:
+        if posix.close(cint(fdi)) != 0:
           raiseIOSelectorsError(osLastError())
       elif Event.Signal in pkey.events:
         var epv = epoll_event()
-        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
           raiseIOSelectorsError(osLastError())
         var nmask, omask: Sigset
         discard sigemptyset(nmask)
@@ -240,12 +242,12 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
         discard sigaddset(nmask, cint(s.fds[fdi].param))
         unblockSignals(nmask, omask)
         dec(s.count)
-        if posix.close(cint(fdi)) == -1:
+        if posix.close(cint(fdi)) != 0:
           raiseIOSelectorsError(osLastError())
       elif Event.Process in pkey.events:
         if Event.Finished notin pkey.events:
           var epv = epoll_event()
-          if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+          if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
             raiseIOSelectorsError(osLastError())
           var nmask, omask: Sigset
           discard sigemptyset(nmask)
@@ -253,21 +255,21 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
           discard sigaddset(nmask, SIGCHLD)
           unblockSignals(nmask, omask)
           dec(s.count)
-        if posix.close(cint(fdi)) == -1:
+        if posix.close(cint(fdi)) != 0:
           raiseIOSelectorsError(osLastError())
     else:
       if pkey.events * {Event.Read, Event.Write} != {}:
         var epv = epoll_event()
-        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
           raiseIOSelectorsError(osLastError())
         dec(s.count)
       elif Event.Timer in pkey.events:
         if Event.Finished notin pkey.events:
           var epv = epoll_event()
-          if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+          if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
             raiseIOSelectorsError(osLastError())
           dec(s.count)
-        if posix.close(cint(fdi)) == -1:
+        if posix.close(cint(fdi)) != 0:
           raiseIOSelectorsError(osLastError())
   clearKey(pkey)
 
@@ -278,7 +280,7 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) =
   doAssert(pkey.ident != 0)
   doAssert(Event.User in pkey.events)
   var epv = epoll_event()
-  if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) == -1:
+  if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
     raiseIOSelectorsError(osLastError())
   dec(s.count)
   clearKey(pkey)
@@ -312,9 +314,9 @@ proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
     new_ts.it_value.tv_sec = new_ts.it_interval.tv_sec
     new_ts.it_value.tv_nsec = new_ts.it_interval.tv_nsec
 
-  if timerfd_settime(fdi.cint, cint(0), new_ts, old_ts) == -1:
+  if timerfd_settime(fdi.cint, cint(0), new_ts, old_ts) != 0:
     raiseIOSelectorsError(osLastError())
-  if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
+  if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) != 0:
     raiseIOSelectorsError(osLastError())
   s.setKey(fdi, events, 0, data)
   inc(s.count)
@@ -342,7 +344,7 @@ when not defined(android):
 
     var epv = epoll_event(events: EPOLLIN or EPOLLRDHUP)
     epv.data.u64 = fdi.uint
-    if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
+    if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) != 0:
       raiseIOSelectorsError(osLastError())
     s.setKey(fdi, {Event.Signal}, signal, data)
     inc(s.count)
@@ -370,7 +372,7 @@ when not defined(android):
     var epv = epoll_event(events: EPOLLIN or EPOLLRDHUP)
     epv.data.u64 = fdi.uint
     epv.events = EPOLLIN or EPOLLRDHUP
-    if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) == -1:
+    if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, fdi.cint, addr epv) != 0:
       raiseIOSelectorsError(osLastError())
     s.setKey(fdi, {Event.Process, Event.Oneshot}, pid, data)
     inc(s.count)
@@ -382,7 +384,7 @@ proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
   s.setKey(fdi, {Event.User}, 0, data)
   var epv = epoll_event(events: EPOLLIN or EPOLLRDHUP)
   epv.data.u64 = ev.efd.uint
-  if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, ev.efd, addr epv) == -1:
+  if epoll_ctl(s.epollFD, EPOLL_CTL_ADD, ev.efd, addr epv) != 0:
     raiseIOSelectorsError(osLastError())
   inc(s.count)
 
@@ -480,7 +482,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
 
       if Event.Oneshot in pkey.events:
         var epv = epoll_event()
-        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, cint(fdi), addr epv) == -1:
+        if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, cint(fdi), addr epv) != 0:
           raiseIOSelectorsError(osLastError())
         # we will not clear key until it will be unregistered, so
         # application can obtain data, but we will decrease counter,
diff --git a/lib/pure/ioselects/ioselectors_kqueue.nim b/lib/pure/ioselects/ioselectors_kqueue.nim
index f4111263a..bb94ea172 100644
--- a/lib/pure/ioselects/ioselectors_kqueue.nim
+++ b/lib/pure/ioselects/ioselectors_kqueue.nim
@@ -116,12 +116,13 @@ proc newSelector*[T](): Selector[T] =
     raiseIOSelectorsError(osLastError())
 
 proc close*[T](s: Selector[T]) =
-  if posix.close(s.kqFD) != 0:
-    raiseIOSelectorsError(osLastError())
+  let res = posix.close(s.kqFD)
   when hasThreadSupport:
     deinitLock(s.changesLock)
     deallocSharedArray(s.fds)
     deallocShared(cast[pointer](s))
+  if res != 0:
+    raiseIOSelectorsError(osLastError())
 
 template clearKey[T](key: ptr SelectorKey[T]) =
   var empty: T
@@ -131,7 +132,7 @@ template clearKey[T](key: ptr SelectorKey[T]) =
 
 proc newSelectEvent*(): SelectEvent =
   var fds: array[2, cint]
-  if posix.pipe(fds) == -1:
+  if posix.pipe(fds) != 0:
     raiseIOSelectorsError(osLastError())
   setNonBlocking(fds[0])
   setNonBlocking(fds[1])
@@ -145,11 +146,11 @@ proc setEvent*(ev: SelectEvent) =
     raiseIOSelectorsError(osLastError())
 
 proc close*(ev: SelectEvent) =
-  if posix.close(cint(ev.rfd)) == -1:
-    raiseIOSelectorsError(osLastError())
-  if posix.close(cint(ev.wfd)) == -1:
-    raiseIOSelectorsError(osLastError())
+  let res1 = posix.close(ev.rfd)
+  let res2 = posix.close(ev.wfd)
   deallocShared(cast[pointer](ev))
+  if res1 != 0 or res2 != 0:
+    raiseIOSelectorsError(osLastError())
 
 template checkFd(s, f) =
   if f >= s.maxFD:
@@ -386,7 +387,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
         when not declared(CACHE_EVENTS):
           flushKQueue(s)
         dec(s.count)
-      if posix.close(cint(pkey.ident)) == -1:
+      if posix.close(cint(pkey.ident)) != 0:
         raiseIOSelectorsError(osLastError())
     elif Event.Signal in pkey.events:
       var nmask, omask: Sigset
@@ -400,7 +401,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
       when not declared(CACHE_EVENTS):
         flushKQueue(s)
       dec(s.count)
-      if posix.close(cint(pkey.ident)) == -1:
+      if posix.close(cint(pkey.ident)) != 0:
         raiseIOSelectorsError(osLastError())
     elif Event.Process in pkey.events:
       if Event.Finished notin pkey.events:
@@ -408,7 +409,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
         when not declared(CACHE_EVENTS):
           flushKQueue(s)
         dec(s.count)
-      if posix.close(cint(pkey.ident)) == -1:
+      if posix.close(cint(pkey.ident)) != 0:
         raiseIOSelectorsError(osLastError())
     elif Event.Vnode in pkey.events:
       modifyKQueue(s, uint(fdi), EVFILT_VNODE, EV_DELETE, 0, 0, nil)
diff --git a/lib/pure/ioselects/ioselectors_poll.nim b/lib/pure/ioselects/ioselectors_poll.nim
index 26fe60b54..9c6f9796f 100644
--- a/lib/pure/ioselects/ioselectors_poll.nim
+++ b/lib/pure/ioselects/ioselectors_poll.nim
@@ -199,7 +199,7 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) =
 
 proc newSelectEvent*(): SelectEvent =
   var fds: array[2, cint]
-  if posix.pipe(fds) == -1:
+  if posix.pipe(fds) != 0:
     raiseIOSelectorsError(osLastError())
   setNonBlocking(fds[0])
   setNonBlocking(fds[1])
@@ -213,11 +213,11 @@ proc setEvent*(ev: SelectEvent) =
     raiseIOSelectorsError(osLastError())
 
 proc close*(ev: SelectEvent) =
-  if posix.close(cint(ev.rfd)) == -1:
-    raiseIOSelectorsError(osLastError())
-  if posix.close(cint(ev.wfd)) == -1:
-    raiseIOSelectorsError(osLastError())
+  let res1 = posix.close(ev.rfd)
+  let res2 = posix.close(ev.wfd)
   deallocShared(cast[pointer](ev))
+  if res1 != 0 or res2 != 0:
+    raiseIOSelectorsError(osLastError())
 
 proc selectInto*[T](s: Selector[T], timeout: int,
                     results: var openarray[ReadyKey]): int =
diff --git a/lib/pure/ioselects/ioselectors_select.nim b/lib/pure/ioselects/ioselectors_select.nim
index 19d68f0fe..7a7d23982 100644
--- a/lib/pure/ioselects/ioselectors_select.nim
+++ b/lib/pure/ioselects/ioselectors_select.nim
@@ -122,17 +122,17 @@ when defined(windows):
                 sizeof(saddr).SockLen) < 0'i32:
       raiseIOSelectorsError(osLastError())
 
-    if winlean.listen(ssock, 1) == -1:
+    if winlean.listen(ssock, 1) != 0:
       raiseIOSelectorsError(osLastError())
 
     var namelen = sizeof(saddr).SockLen
     if getsockname(ssock, cast[ptr SockAddr](addr(saddr)),
-                   addr(namelen)) == -1'i32:
+                   addr(namelen)) != 0'i32:
       raiseIOSelectorsError(osLastError())
 
     saddr.sin_addr.s_addr = 0x0100007F
     if winlean.connect(wsock, cast[ptr SockAddr](addr(saddr)),
-                       sizeof(saddr).SockLen) == -1:
+                       sizeof(saddr).SockLen) != 0:
       raiseIOSelectorsError(osLastError())
     namelen = sizeof(saddr).SockLen
     rsock = winlean.accept(ssock, cast[ptr SockAddr](addr(saddr)),
@@ -140,14 +140,14 @@ when defined(windows):
     if rsock == SocketHandle(-1):
       raiseIOSelectorsError(osLastError())
 
-    if winlean.closesocket(ssock) == -1:
+    if winlean.closesocket(ssock) != 0:
       raiseIOSelectorsError(osLastError())
 
     var mode = clong(1)
-    if ioctlsocket(rsock, FIONBIO, addr(mode)) == -1:
+    if ioctlsocket(rsock, FIONBIO, addr(mode)) != 0:
       raiseIOSelectorsError(osLastError())
     mode = clong(1)
-    if ioctlsocket(wsock, FIONBIO, addr(mode)) == -1:
+    if ioctlsocket(wsock, FIONBIO, addr(mode)) != 0:
       raiseIOSelectorsError(osLastError())
 
     result = cast[SelectEvent](allocShared0(sizeof(SelectEventImpl)))
@@ -161,14 +161,16 @@ when defined(windows):
       raiseIOSelectorsError(osLastError())
 
   proc close*(ev: SelectEvent) =
-    discard winlean.closesocket(ev.rsock)
-    discard winlean.closesocket(ev.wsock)
+    let res1 = winlean.closesocket(ev.rsock)
+    let res2 = winlean.closesocket(ev.wsock)
     deallocShared(cast[pointer](ev))
+    if res1 != 0 or res2 != 0:
+      raiseIOSelectorsError(osLastError())
 
 else:
   proc newSelectEvent*(): SelectEvent =
     var fds: array[2, cint]
-    if posix.pipe(fds) == -1:
+    if posix.pipe(fds) != 0:
       raiseIOSelectorsError(osLastError())
     setNonBlocking(fds[0])
     setNonBlocking(fds[1])
@@ -182,11 +184,11 @@ else:
       raiseIOSelectorsError(osLastError())
 
   proc close*(ev: SelectEvent) =
-    if posix.close(cint(ev.rsock)) == -1:
-      raiseIOSelectorsError(osLastError())
-    if posix.close(cint(ev.wsock)) == -1:
-      raiseIOSelectorsError(osLastError())
+    let res1 = posix.close(cint(ev.rsock))
+    let res2 = posix.close(cint(ev.wsock))
     deallocShared(cast[pointer](ev))
+    if res1 != 0 or res2 != 0:
+      raiseIOSelectorsError(osLastError())
 
 proc setSelectKey[T](s: Selector[T], fd: SocketHandle, events: set[Event],
                      data: T) =
diff --git a/lib/upcoming/asyncdispatch.nim b/lib/upcoming/asyncdispatch.nim
index 80a4f0e4f..17ddb1a82 100644
--- a/lib/upcoming/asyncdispatch.nim
+++ b/lib/upcoming/asyncdispatch.nim
@@ -856,7 +856,9 @@ when defined(windows) or defined(nimdoc):
         if unregisterWait(pcd.waitFd) == 0:
           let err = osLastError()
           if err.int32 != ERROR_IO_PENDING:
-            raiseOSError(osLastError())
+            deallocShared(cast[pointer](pcd))
+            discard wsaCloseEvent(hEvent)
+            raiseOSError(err)
         if cb(fd):
           # callback returned `true`, so we free all allocated resources
           deallocShared(cast[pointer](pcd))
@@ -880,9 +882,10 @@ when defined(windows) or defined(nimdoc):
                                     cast[WAITORTIMERCALLBACK](waitableCallback),
                                        cast[pointer](pcd), INFINITE, flags):
               # pcd.ovl will be unrefed in poll()
-              discard wsaCloseEvent(hEvent)
+              let err = osLastError()
               deallocShared(cast[pointer](pcd))
-              raiseOSError(osLastError())
+              discard wsaCloseEvent(hEvent)
+              raiseOSError(err)
             else:
               # we incref `pcd.ovl` and `protect` callback one more time,
               # because it will be unrefed and disposed in `poll()` after
@@ -897,19 +900,21 @@ when defined(windows) or defined(nimdoc):
     # This is main part of `hacky way` is using WSAEventSelect, so `hEvent`
     # will be signaled when appropriate `mask` events will be triggered.
     if wsaEventSelect(fd.SocketHandle, hEvent, mask) != 0:
+      let err = osLastError()
       GC_unref(ol)
       deallocShared(cast[pointer](pcd))
       discard wsaCloseEvent(hEvent)
-      raiseOSError(osLastError())
+      raiseOSError(err)
 
     pcd.ovl = ol
     if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
                                     cast[WAITORTIMERCALLBACK](waitableCallback),
                                        cast[pointer](pcd), INFINITE, flags):
+      let err = osLastError()
       GC_unref(ol)
       deallocShared(cast[pointer](pcd))
       discard wsaCloseEvent(hEvent)
-      raiseOSError(osLastError())
+      raiseOSError(err)
     p.handles.incl(fd)
 
   proc addRead*(fd: AsyncFD, cb: Callback) =
@@ -963,12 +968,25 @@ when defined(windows) or defined(nimdoc):
     if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
                                     cast[WAITORTIMERCALLBACK](waitableCallback),
                                     cast[pointer](pcd), timeout.Dword, flags):
+      let err = osLastError()
       GC_unref(ol)
       deallocShared(cast[pointer](pcd))
       discard closeHandle(hEvent)
-      raiseOSError(osLastError())
+      raiseOSError(err)
     p.handles.incl(handleFD)
 
+  template closeWaitable(handle: untyped) =
+    let waitFd = pcd.waitFd
+    deallocShared(cast[pointer](pcd))
+    p.handles.excl(fd)
+    if unregisterWait(waitFd) == 0:
+        let err = osLastError()
+        if err.int32 != ERROR_IO_PENDING:
+          discard closeHandle(handle)
+          raiseOSError(err)
+    if closeHandle(handle) == 0:
+      raiseOSError(osLastError())
+
   proc addTimer*(timeout: int, oneshot: bool, cb: Callback) =
     ## Registers callback ``cb`` to be called when timer expired.
     ## ``timeout`` - timeout value in milliseconds.
@@ -989,13 +1007,7 @@ when defined(windows) or defined(nimdoc):
     proc timercb(fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
       let res = cb(fd)
       if res or oneshot:
-        if unregisterWait(pcd.waitFd) == 0:
-          let err = osLastError()
-          if err.int32 != ERROR_IO_PENDING:
-            raiseOSError(osLastError())
-        discard closeHandle(hEvent)
-        deallocShared(cast[pointer](pcd))
-        p.handles.excl(fd)
+        closeWaitable(hEvent)
       else:
         # if callback returned `false`, then it wants to be called again, so
         # we need to ref and protect `pcd.ovl` again, because it will be
@@ -1018,13 +1030,7 @@ when defined(windows) or defined(nimdoc):
     var flags = WT_EXECUTEINWAITTHREAD.Dword
 
     proc proccb(fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
-      if unregisterWait(pcd.waitFd) == 0:
-        let err = osLastError()
-        if err.int32 != ERROR_IO_PENDING:
-          raiseOSError(osLastError())
-      discard closeHandle(hProcess)
-      deallocShared(cast[pointer](pcd))
-      p.handles.excl(fd)
+      closeWaitable(hProcess)
       discard cb(fd)
 
     registerWaitableHandle(p, hProcess, flags, pcd, INFINITE, proccb)
@@ -1052,20 +1058,21 @@ when defined(windows) or defined(nimdoc):
     ## Unregisters event ``ev``.
     if ev.hWaiter != 0:
       let p = getGlobalDispatcher()
+      p.handles.excl(AsyncFD(ev.hEvent))
       if unregisterWait(ev.hWaiter) == 0:
         let err = osLastError()
         if err.int32 != ERROR_IO_PENDING:
-          raiseOSError(osLastError())
-      p.handles.excl(AsyncFD(ev.hEvent))
+          raiseOSError(err)
       ev.hWaiter = 0
     else:
       raise newException(ValueError, "Event is not registered!")
 
   proc close*(ev: AsyncEvent) =
     ## Closes event ``ev``.
-    if closeHandle(ev.hEvent) == 0:
-      raiseOSError(osLastError())
+    let res = closeHandle(ev.hEvent)
     deallocShared(cast[pointer](ev))
+    if res == 0:
+      raiseOSError(osLastError())
 
   proc addEvent*(ev: AsyncEvent, cb: Callback) =
     ## Registers callback ``cb`` to be called when ``ev`` will be signaled
@@ -1082,8 +1089,8 @@ when defined(windows) or defined(nimdoc):
       if cb(fd):
         # we need this check to avoid exception, if `unregister(event)` was
         # called in callback.
-        if ev.hWaiter != 0: unregister(ev)
         deallocShared(cast[pointer](pcd))
+        if ev.hWaiter != 0: unregister(ev)
       else:
         # if callback returned `false`, then it wants to be called again, so
         # we need to ref and protect `pcd.ovl` again, because it will be