summary refs log tree commit diff stats
path: root/lib/pure/ioselects/ioselectors_epoll.nim
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@gmail.com>2017-11-24 16:25:03 +0000
committerDominik Picheta <dominikpicheta@gmail.com>2017-11-24 16:25:03 +0000
commitd6870f2e8957b88e0ebc6b4e3308361862b48524 (patch)
treedd11a4f30f459c4f637cdb5def08efe1c353e84b /lib/pure/ioselects/ioselectors_epoll.nim
parent3db460f5045e790b54ea3825713c87e92679e8ab (diff)
downloadNim-d6870f2e8957b88e0ebc6b4e3308361862b48524.tar.gz
Multiple improvements to selectors.
* Added ``getFd`` procedure for retrieving the underlying
  selector's FD.
* Selectors module's procedures now accept an ``int`` as well as a
  ``SocketHandle``.
* ReadyKey now contains the error code for Event.Error events.
Diffstat (limited to 'lib/pure/ioselects/ioselectors_epoll.nim')
-rw-r--r--lib/pure/ioselects/ioselectors_epoll.nim21
1 files changed, 17 insertions, 4 deletions
diff --git a/lib/pure/ioselects/ioselectors_epoll.nim b/lib/pure/ioselects/ioselectors_epoll.nim
index 35cdace09..144b4ce8d 100644
--- a/lib/pure/ioselects/ioselectors_epoll.nim
+++ b/lib/pure/ioselects/ioselectors_epoll.nim
@@ -141,7 +141,7 @@ template checkFd(s, f) =
   if f >= s.maxFD:
     raiseIOSelectorsError("Maximum number of descriptors is exhausted!")
 
-proc registerHandle*[T](s: Selector[T], fd: SocketHandle,
+proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
                         events: set[Event], data: T) =
   let fdi = int(fd)
   s.checkFd(fdi)
@@ -156,7 +156,7 @@ proc registerHandle*[T](s: Selector[T], fd: SocketHandle,
       raiseIOSelectorsError(osLastError())
     inc(s.count)
 
-proc updateHandle*[T](s: Selector[T], fd: SocketHandle, events: set[Event]) =
+proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle, events: set[Event]) =
   let maskEvents = {Event.Timer, Event.Signal, Event.Process, Event.Vnode,
                     Event.User, Event.Oneshot, Event.Error}
   let fdi = int(fd)
@@ -391,9 +391,19 @@ proc selectInto*[T](s: Selector[T], timeout: int,
       let pevents = resTable[i].events
       var pkey = addr(s.fds[fdi])
       doAssert(pkey.ident != 0)
-      var rkey = ReadyKey(fd: int(fdi), events: {})
+      var rkey = ReadyKey(fd: fdi, events: {})
 
       if (pevents and EPOLLERR) != 0 or (pevents and EPOLLHUP) != 0:
+        if (pevents and EPOLLHUP) != 0:
+          rkey.errorCode = ECONNRESET.OSErrorCode
+        else:
+          # Try reading SO_ERROR from fd.
+          var error: cint
+          var size = sizeof(error).SockLen
+          if getsockopt(fdi.SocketHandle, SOL_SOCKET, SO_ERROR, addr(error),
+                        addr(size)) == 0'i32:
+            rkey.errorCode = error.OSErrorCode
+
         rkey.events.incl(Event.Error)
       if (pevents and EPOLLOUT) != 0:
         rkey.events.incl(Event.Write)
@@ -481,7 +491,7 @@ template isEmpty*[T](s: Selector[T]): bool =
   (s.count == 0)
 
 proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} =
-  return s.fds[fd].ident != 0
+  return s.fds[fd.int].ident != 0
 
 proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T =
   let fdi = int(fd)
@@ -515,3 +525,6 @@ template withData*[T](s: Selector[T], fd: SocketHandle|int, value, body1,
     body1
   else:
     body2
+
+proc getFd*[T](s: Selector[T]): int =
+  return s.epollFd.int
\ No newline at end of file