Fix select routine to return EAGAIN when timeout is 0 and no fds are
ready
This commit is contained in:
Manoj Ampalam 2016-03-07 13:02:31 -08:00
parent 73cab1c657
commit 991be1f492
1 changed files with 22 additions and 12 deletions

View File

@ -420,12 +420,12 @@ w32_fcntl(int fd, int cmd, ... /* arg */) {
int int
w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds, w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds,
const struct timeval *timeout) { const struct timeval *timeout) {
ULONGLONG ticks_start = GetTickCount64(), ticks_now; ULONGLONG ticks_start = GetTickCount64(), ticks_spent;
w32_fd_set read_ready_fds, write_ready_fds; w32_fd_set read_ready_fds, write_ready_fds;
HANDLE events[SELECT_EVENT_LIMIT]; HANDLE events[SELECT_EVENT_LIMIT];
int num_events = 0; int num_events = 0;
int in_set_fds = 0, out_ready_fds = 0, i; int in_set_fds = 0, out_ready_fds = 0, i;
unsigned int time_milliseconds = 0; unsigned int time_ms_rem = 0;
errno = 0; errno = 0;
/* TODO - the size of these can be reduced based on fds */ /* TODO - the size of these can be reduced based on fds */
@ -433,7 +433,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
memset(&write_ready_fds, 0, sizeof(w32_fd_set)); memset(&write_ready_fds, 0, sizeof(w32_fd_set));
if (timeout) if (timeout)
time_milliseconds = timeout->tv_sec * 100 + timeout->tv_usec / 1000; time_ms_rem = timeout->tv_sec * 100 + timeout->tv_usec / 1000;
if (fds > MAX_FDS) { if (fds > MAX_FDS) {
errno = EINVAL; errno = EINVAL;
@ -477,7 +477,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
return -1; return -1;
} }
debug2("Total in fds:%d", in_set_fds); debug3("Total in fds:%d", in_set_fds);
/* /*
* start async io on selected fds if needed and pick up any events * start async io on selected fds if needed and pick up any events
* that select needs to listen on * that select needs to listen on
@ -537,15 +537,18 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
/* wait for io if none is already ready */ /* wait for io if none is already ready */
while (out_ready_fds == 0) { while (out_ready_fds == 0) {
ticks_now = GetTickCount64(); ticks_spent = GetTickCount64() - ticks_start;
if (time_milliseconds < (ticks_now - ticks_start)) {
errno = ETIMEDOUT; if (timeout != NULL) {
debug("select timing out"); if (time_ms_rem < ticks_spent) {
return -1; errno = ETIMEDOUT;
debug("select timing out");
return -1;
}
time_ms_rem -= ticks_spent & 0xffffffff;
} }
if (0 != wait_for_any_event(events, num_events, if (0 != wait_for_any_event(events, num_events, time_ms_rem))
time_milliseconds - ((ticks_now - ticks_start) & 0xffffffff)))
return -1; return -1;
/* check on fd status */ /* check on fd status */
@ -569,8 +572,15 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
} }
} }
if (out_ready_fds == 0) if (out_ready_fds == 0) {
if (timeout == 0) {
/* not timeout specified, return EAGAIN if none of fds are ready */
errno = EAGAIN;
return -1;
}
debug2("wait ended without any IO completion, looping again"); debug2("wait ended without any IO completion, looping again");
}
}; };
/* clear out fds that are not ready yet */ /* clear out fds that are not ready yet */