libev/ev_select.c in ebb-0.2.1 vs libev/ev_select.c in ebb-0.3.0
- old
+ new
@@ -52,10 +52,12 @@
#endif
#if EV_SELECT_IS_WINSOCKET
# undef EV_SELECT_USE_FD_SET
# define EV_SELECT_USE_FD_SET 1
+# undef NFDBITS
+# define NFDBITS 0
#endif
#if !EV_SELECT_USE_FD_SET
# define NFDBYTES (NFDBITS / 8)
#endif
@@ -75,19 +77,28 @@
SOCKET handle = anfds [fd].handle;
#else
int handle = fd;
#endif
- if (nev & EV_READ)
- FD_SET (handle, (fd_set *)vec_ri);
- else
- FD_CLR (handle, (fd_set *)vec_ri);
+ /* FD_SET is broken on windows (it adds the fd to a set twice or more,
+ * which eventually leads to overflows). Need to call it only on changes.
+ */
+ #if EV_SELECT_IS_WINSOCKET
+ if ((oev ^ nev) & EV_READ)
+ #endif
+ if (nev & EV_READ)
+ FD_SET (handle, (fd_set *)vec_ri);
+ else
+ FD_CLR (handle, (fd_set *)vec_ri);
- if (nev & EV_WRITE)
- FD_SET (handle, (fd_set *)vec_wi);
- else
- FD_CLR (handle, (fd_set *)vec_wi);
+ #if EV_SELECT_IS_WINSOCKET
+ if ((oev ^ nev) & EV_WRITE)
+ #endif
+ if (nev & EV_WRITE)
+ FD_SET (handle, (fd_set *)vec_wi);
+ else
+ FD_CLR (handle, (fd_set *)vec_wi);
#else
int word = fd / NFDBITS;
fd_mask mask = 1UL << (fd % NFDBITS);
@@ -98,10 +109,13 @@
vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES);
vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */
vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES);
vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */
+ #ifdef _WIN32
+ vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */
+ #endif
for (; vec_max < new_max; ++vec_max)
((fd_mask *)vec_ri) [vec_max] =
((fd_mask *)vec_wi) [vec_max] = 0;
}
@@ -120,23 +134,35 @@
static void
select_poll (EV_P_ ev_tstamp timeout)
{
struct timeval tv;
int res;
+ int fd_setsize;
+ tv.tv_sec = (long)timeout;
+ tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
+
#if EV_SELECT_USE_FD_SET
- memcpy (vec_ro, vec_ri, sizeof (fd_set));
- memcpy (vec_wo, vec_wi, sizeof (fd_set));
+ fd_setsize = sizeof (fd_set);
#else
- memcpy (vec_ro, vec_ri, vec_max * NFDBYTES);
- memcpy (vec_wo, vec_wi, vec_max * NFDBYTES);
+ fd_setsize = vec_max * NFDBYTES;
#endif
- tv.tv_sec = (long)timeout;
- tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6);
+ memcpy (vec_ro, vec_ri, fd_setsize);
+ memcpy (vec_wo, vec_wi, fd_setsize);
+#ifdef _WIN32
+ /* pass in the write set as except set.
+ * the idea behind this is to work around a windows bug that causes
+ * errors to be reported as an exception and not by setting
+ * the writable bit. this is so uncontrollably lame.
+ */
+ memcpy (vec_eo, vec_wi, fd_setsize);
+ res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv);
+#else
res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
+#endif
if (expect_false (res < 0))
{
#if EV_SELECT_IS_WINSOCKET
errno = WSAGetLastError ();
@@ -190,10 +216,13 @@
int handle = fd;
#endif
if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
+ #ifdef _WIN32
+ if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;
+ #endif
if (expect_true (events))
fd_event (EV_A_ fd, events);
}
}
@@ -204,10 +233,13 @@
int word, bit;
for (word = vec_max; word--; )
{
fd_mask word_r = ((fd_mask *)vec_ro) [word];
fd_mask word_w = ((fd_mask *)vec_wo) [word];
+ #ifdef _WIN32
+ word_w |= ((fd_mask *)vec_eo) [word];
+ #endif
if (word_r || word_w)
for (bit = NFDBITS; bit--; )
{
fd_mask mask = 1UL << bit;
@@ -236,9 +268,12 @@
vec_max = FD_SETSIZE / 32;
vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri);
vec_ro = ev_malloc (sizeof (fd_set));
vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi);
vec_wo = ev_malloc (sizeof (fd_set));
+ #ifdef _WIN32
+ vec_eo = ev_malloc (sizeof (fd_set));
+ #endif
#else
vec_max = 0;
vec_ri = 0;
vec_ri = 0;
vec_wo = 0;