fix hangs reading stdin on Windows

This commit is contained in:
Brent Cook 2015-03-08 16:39:48 -05:00
parent 213eb9465e
commit 148aebdbb1

View File

@ -44,6 +44,8 @@ conn_has_oob_data(int fd)
static int static int
is_socket(int fd) is_socket(int fd)
{ {
if (fd < 3)
return 0;
WSANETWORKEVENTS events; WSANETWORKEVENTS events;
return (WSAEnumNetworkEvents((SOCKET)fd, NULL, &events) == 0); return (WSAEnumNetworkEvents((SOCKET)fd, NULL, &events) == 0);
} }
@ -160,10 +162,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
nfds_t i; nfds_t i;
int timespent_ms, looptime_ms; int timespent_ms, looptime_ms;
#define FD_IS_SOCKET (1 << 0)
int fd_state[FD_SETSIZE];
int num_fds;
/* /*
* select machinery * select machinery
*/ */
@ -190,14 +188,12 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_ZERO(&wfds); FD_ZERO(&wfds);
FD_ZERO(&efds); FD_ZERO(&efds);
num_fds = 0;
num_sockets = 0; num_sockets = 0;
num_handles = 0; num_handles = 0;
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
if ((int)pfds[i].fd < 0) { if ((int)pfds[i].fd < 0)
continue; continue;
}
if (is_socket(pfds[i].fd)) { if (is_socket(pfds[i].fd)) {
if (num_sockets >= FD_SETSIZE) { if (num_sockets >= FD_SETSIZE) {
@ -205,8 +201,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
return -1; return -1;
} }
fd_state[num_fds] = FD_IS_SOCKET;
FD_SET(pfds[i].fd, &efds); FD_SET(pfds[i].fd, &efds);
if (pfds[i].events & if (pfds[i].events &
@ -229,8 +223,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
handles[num_handles++] = handles[num_handles++] =
(HANDLE)_get_osfhandle(pfds[i].fd); (HANDLE)_get_osfhandle(pfds[i].fd);
} }
num_fds++;
} }
/* /*
@ -254,21 +246,22 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
* than simply triggering if there is space available. * than simply triggering if there is space available.
*/ */
timespent_ms = 0; timespent_ms = 0;
wait_rc = 0; wait_rc = WAIT_FAILED;
if (timeout_ms < 0) { if (timeout_ms < 0)
timeout_ms = INFINITE; timeout_ms = INFINITE;
}
looptime_ms = timeout_ms > 100 ? 100 : timeout_ms; looptime_ms = timeout_ms > 100 ? 100 : timeout_ms;
do { do {
struct timeval tv = {0, looptime_ms * 1000}; struct timeval tv = {0, looptime_ms * 1000};
int handle_signaled = 0;
/* /*
* Check if any file handles have signaled * Check if any file handles have signaled
*/ */
if (num_handles) { if (num_handles) {
wait_rc = WaitForMultipleObjects(num_handles, handles, FALSE, 0); wait_rc = WaitForMultipleObjects(num_handles, handles,
FALSE, 0);
if (wait_rc == WAIT_FAILED) { if (wait_rc == WAIT_FAILED) {
/* /*
* The documentation for WaitForMultipleObjects * The documentation for WaitForMultipleObjects
@ -285,18 +278,20 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
/* /*
* If we signaled on a file handle, don't wait on the sockets. * If we signaled on a file handle, don't wait on the sockets.
*/ */
if (wait_rc >= WAIT_OBJECT_0) if (wait_rc >= WAIT_OBJECT_0 &&
(wait_rc <= WAIT_OBJECT_0 + num_handles - 1)) {
tv.tv_usec = 0; tv.tv_usec = 0;
handle_signaled = 1;
}
/* /*
* Check if any sockets have signaled * Check if any sockets have signaled
*/ */
rc = select(0, &rfds, &wfds, &efds, &tv); rc = select(0, &rfds, &wfds, &efds, &tv);
if (rc == SOCKET_ERROR) { if (!handle_signaled && rc == SOCKET_ERROR)
return wsa_select_errno(WSAGetLastError()); return wsa_select_errno(WSAGetLastError());
}
if (wait_rc >= WAIT_OBJECT_0 || (num_sockets && rc > 0)) if (handle_signaled || (num_sockets && rc > 0))
break; break;
timespent_ms += looptime_ms; timespent_ms += looptime_ms;
@ -305,14 +300,14 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
rc = 0; rc = 0;
num_handles = 0; num_handles = 0;
num_fds = 0;
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
pfds[i].revents = 0; pfds[i].revents = 0;
if ((int)pfds[i].fd < 0) if ((int)pfds[i].fd < 0)
continue; continue;
if (fd_state[num_fds] & FD_IS_SOCKET) { if (is_socket(pfds[i].fd)) {
pfds[i].revents = compute_select_revents(pfds[i].fd, pfds[i].revents = compute_select_revents(pfds[i].fd,
pfds[i].events, &rfds, &wfds, &efds); pfds[i].events, &rfds, &wfds, &efds);
@ -323,8 +318,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
num_handles++; num_handles++;
} }
num_fds++;
if (pfds[i].revents) if (pfds[i].revents)
rc++; rc++;
} }