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;