Workaround for libev handle caching bug on windows
authorBert Belder <bertbelder@gmail.com>
Mon, 24 Jan 2011 16:26:22 +0000 (17:26 +0100)
committerRyan Dahl <ry@tinyclouds.org>
Mon, 24 Jan 2011 18:34:18 +0000 (10:34 -0800)
The windows socket api uses handles, not fds. Libev caches the handle
associated with an fd, and uses this handle when updating the (also cached)
handle set that goes into select(). When an fd is closed and subsequently
re-used before the event loop returns to libev, libev fails to detect
properly that the handle changed. And even if it does, the cached handle of
the closed socket is overwritten by the new handle, so by the time libev
tries to update the select fdset it has forgotten which handle to remove
from it. This is solved by a simple hook ev_fd_closed that makes it clear
its caches before the fd is re-used.

deps/libev/ev.c
deps/libev/ev.h
src/node_net.cc

index 6d8676d..63237d7 100644 (file)
@@ -1033,6 +1033,23 @@ fd_kill (EV_P_ int fd)
     }
 }
 
+/* notify libev that an fd was closed. required on windows when a closed */
+/* fd may be reused during before backend_modify is called again */
+void noinline
+ev_fd_closed(EV_P_ int fd)
+{
+#ifdef _WIN32
+  if (fd < anfdmax) {
+    ANFD *anfd = anfds + fd;
+
+    backend_modify (EV_A_ fd, anfd->events, 0);
+    anfd->events = 0;
+
+    fd_change (EV_A_ fd, EV__IOFDSET | EV_ANFD_REIFY);
+  }
+#endif
+}
+
 /* check whether the given fd is actually valid, for error recovery */
 inline_size int
 fd_valid (int fd)
index 9edf656..65595c8 100644 (file)
@@ -731,6 +731,10 @@ int  ev_clear_pending  (EV_P_ void *w);
 void ev_io_start       (EV_P_ ev_io *w);
 void ev_io_stop        (EV_P_ ev_io *w);
 
+/* notify libev that an fd was closed. required on windows when a closed */
+/* fd may be reused during before backend_modify is called again */
+void ev_fd_closed(EV_P_ int fd);
+
 void ev_timer_start    (EV_P_ ev_timer *w);
 void ev_timer_stop     (EV_P_ ev_timer *w);
 /* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */
index 2dc6f9c..21b9887 100644 (file)
@@ -375,6 +375,10 @@ static Handle<Value> Close(const Arguments& args) {
     return ThrowException(ErrnoException(errno, "close"));
   }
 
+#ifdef __MINGW32__
+  ev_fd_closed(EV_DEFAULT_UC_ fd);
+#endif
+
   return Undefined();
 }