Fixes in select routine to respect incoming fd_set size
This commit is contained in:
Manoj Ampalam 2016-03-07 11:05:46 -08:00
parent d871c325aa
commit 73cab1c657

View File

@ -416,17 +416,19 @@ w32_fcntl(int fd, int cmd, ... /* arg */) {
} }
} }
#define SELECT_EVENT_LIMIT 32
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_now;
w32_fd_set read_ready_fds, write_ready_fds; w32_fd_set read_ready_fds, write_ready_fds;
HANDLE events[32]; 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_milliseconds = 0;
errno = 0; errno = 0;
/* TODO - the size of these can be reduced based on fds */
memset(&read_ready_fds, 0, sizeof(w32_fd_set)); memset(&read_ready_fds, 0, sizeof(w32_fd_set));
memset(&write_ready_fds, 0, sizeof(w32_fd_set)); memset(&write_ready_fds, 0, sizeof(w32_fd_set));
@ -487,6 +489,11 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
return -1; return -1;
if ((fd_table.w32_ios[i]->type == SOCK_FD) if ((fd_table.w32_ios[i]->type == SOCK_FD)
&& (fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) { && (fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
if (num_events == SELECT_EVENT_LIMIT) {
debug("ERROR: max #events reached for select");
errno = ENOMEM;
return -1;
}
events[num_events++] = fd_table.w32_ios[i]->read_overlapped.hEvent; events[num_events++] = fd_table.w32_ios[i]->read_overlapped.hEvent;
} }
} }
@ -496,6 +503,11 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
return -1; return -1;
if ((fd_table.w32_ios[i]->type == SOCK_FD) if ((fd_table.w32_ios[i]->type == SOCK_FD)
&& (fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) { && (fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
if (num_events == SELECT_EVENT_LIMIT) {
debug("ERROR: max #events reached for select");
errno = ENOMEM;
return -1;
}
events[num_events++] = fd_table.w32_ios[i]->write_overlapped.hEvent; events[num_events++] = fd_table.w32_ios[i]->write_overlapped.hEvent;
} }
} }
@ -523,17 +535,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
} }
} }
/* if io on some fds is already ready, return */ /* wait for io if none is already ready */
if (out_ready_fds) { while (out_ready_fds == 0) {
if (readfds)
*readfds = read_ready_fds;
if (writefds)
*writefds = write_ready_fds;
debug2("IO ready:%d, no wait", out_ready_fds);
return out_ready_fds;
}
do {
ticks_now = GetTickCount64(); ticks_now = GetTickCount64();
if (time_milliseconds < (ticks_now - ticks_start)) { if (time_milliseconds < (ticks_now - ticks_start)) {
errno = ETIMEDOUT; errno = ETIMEDOUT;
@ -566,17 +569,21 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
} }
} }
if (out_ready_fds) if (out_ready_fds == 0)
break; debug2("wait ended without any IO completion, looping again");
};
debug2("wait ended without any IO completion, looping again");
} while (1);
/* clear out fds that are not ready yet */
if (readfds) if (readfds)
*readfds = read_ready_fds; for (i = 0; i < fds; i++)
if (FD_ISSET(i, readfds) && (!FD_ISSET(i, &read_ready_fds)))
FD_CLR(i, readfds);
if (writefds) if (writefds)
*writefds = write_ready_fds; for (i = 0; i < fds; i++)
if (FD_ISSET(i, writefds) && (!FD_ISSET(i, &write_ready_fds)))
FD_CLR(i, writefds);
return out_ready_fds; return out_ready_fds;