select: Don't timeout without setting descriptor arrays to all zero

* select.cc (copyfd_set): Remove.
        (select): Don't copy local wait fd arrays over to returned fd arrays
        since bits set there are not accounted for in return value.  Zero out
        returned fd arrays instead.  Always call sel.poll even in case of a
        timeout.  Always zero out fd array when timing out.  Convert while/do
        to do/while for clarity.  Use dedicated variable as return value to
        decouple return value from artificial return code from sel.wait.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2016-01-09 14:53:06 +01:00
parent e0d4e3fec7
commit 3069a93fbe
1 changed files with 20 additions and 15 deletions

View File

@ -77,8 +77,6 @@ details. */
(fd_set *) __res; \ (fd_set *) __res; \
}) })
#define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n));
#define set_handle_or_return_if_not_open(h, s) \ #define set_handle_or_return_if_not_open(h, s) \
h = (s)->fh->get_io_handle_cyg (); \ h = (s)->fh->get_io_handle_cyg (); \
if (cygheap->fdtab.not_open ((s)->fd)) \ if (cygheap->fdtab.not_open ((s)->fd)) \
@ -132,6 +130,7 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
DWORD ms) DWORD ms)
{ {
int res = select_stuff::select_loop; int res = select_stuff::select_loop;
int ret = 0;
/* Record the current time for later use. */ /* Record the current time for later use. */
LONGLONG start_time = gtod.msecs (); LONGLONG start_time = gtod.msecs ();
@ -144,7 +143,7 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
fd_set *w = allocfd_set (maxfds); fd_set *w = allocfd_set (maxfds);
fd_set *e = allocfd_set (maxfds); fd_set *e = allocfd_set (maxfds);
while (res == select_stuff::select_loop) do
{ {
/* Build the select record per fd linked list and set state as /* Build the select record per fd linked list and set state as
needed. */ needed. */
@ -187,14 +186,15 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_printf ("res %d", res); select_printf ("res %d", res);
if (res >= 0) if (res >= 0)
{ {
copyfd_set (readfds, r, maxfds); UNIX_FD_ZERO (readfds, maxfds);
copyfd_set (writefds, w, maxfds); UNIX_FD_ZERO (writefds, maxfds);
copyfd_set (exceptfds, e, maxfds); UNIX_FD_ZERO (exceptfds, maxfds);
if (res == select_stuff::select_set_zero) /* Set bit mask from sel records even in case of a timeout so we
res = 0; don't miss one. This also sets ret to the right value >= 0,
else matching the number of bits set in the fds records. */
/* Set the bit mask from sel records */ ret = sel.poll (readfds, writefds, exceptfds);
res = sel.poll (readfds, writefds, exceptfds) ?: select_stuff::select_loop; if (!ret && res != select_stuff::select_set_zero)
res = select_stuff::select_loop;
} }
/* Always clean up everything here. If we're looping then build it /* Always clean up everything here. If we're looping then build it
all up again. */ all up again. */
@ -208,7 +208,11 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
if (now > (start_time + ms)) if (now > (start_time + ms))
{ {
select_printf ("timed out after verification"); select_printf ("timed out after verification");
res = 0; /* Set descriptor bits to zero per POSIX. */
UNIX_FD_ZERO (readfds, maxfds);
UNIX_FD_ZERO (writefds, maxfds);
UNIX_FD_ZERO (exceptfds, maxfds);
ret = res = 0;
} }
else else
{ {
@ -218,10 +222,11 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
} }
} }
} }
while (res == select_stuff::select_loop);
if (res < -1) if (res < 0)
res = -1; ret = -1;
return res; return ret;
} }
extern "C" int extern "C" int