fix hangs reading stdin on Windows
This commit is contained in:
parent
213eb9465e
commit
148aebdbb1
@ -44,6 +44,8 @@ conn_has_oob_data(int fd)
|
||||
static int
|
||||
is_socket(int fd)
|
||||
{
|
||||
if (fd < 3)
|
||||
return 0;
|
||||
WSANETWORKEVENTS events;
|
||||
return (WSAEnumNetworkEvents((SOCKET)fd, NULL, &events) == 0);
|
||||
}
|
||||
@ -160,10 +162,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
|
||||
nfds_t i;
|
||||
int timespent_ms, looptime_ms;
|
||||
|
||||
#define FD_IS_SOCKET (1 << 0)
|
||||
int fd_state[FD_SETSIZE];
|
||||
int num_fds;
|
||||
|
||||
/*
|
||||
* select machinery
|
||||
*/
|
||||
@ -190,14 +188,12 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
FD_ZERO(&efds);
|
||||
num_fds = 0;
|
||||
num_sockets = 0;
|
||||
num_handles = 0;
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
if ((int)pfds[i].fd < 0) {
|
||||
if ((int)pfds[i].fd < 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_socket(pfds[i].fd)) {
|
||||
if (num_sockets >= FD_SETSIZE) {
|
||||
@ -205,8 +201,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd_state[num_fds] = FD_IS_SOCKET;
|
||||
|
||||
FD_SET(pfds[i].fd, &efds);
|
||||
|
||||
if (pfds[i].events &
|
||||
@ -229,8 +223,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
|
||||
handles[num_handles++] =
|
||||
(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.
|
||||
*/
|
||||
timespent_ms = 0;
|
||||
wait_rc = 0;
|
||||
wait_rc = WAIT_FAILED;
|
||||
|
||||
if (timeout_ms < 0) {
|
||||
if (timeout_ms < 0)
|
||||
timeout_ms = INFINITE;
|
||||
}
|
||||
looptime_ms = timeout_ms > 100 ? 100 : timeout_ms;
|
||||
|
||||
do {
|
||||
struct timeval tv = {0, looptime_ms * 1000};
|
||||
int handle_signaled = 0;
|
||||
|
||||
/*
|
||||
* Check if any file handles have signaled
|
||||
*/
|
||||
if (num_handles) {
|
||||
wait_rc = WaitForMultipleObjects(num_handles, handles, FALSE, 0);
|
||||
wait_rc = WaitForMultipleObjects(num_handles, handles,
|
||||
FALSE, 0);
|
||||
if (wait_rc == WAIT_FAILED) {
|
||||
/*
|
||||
* 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 (wait_rc >= WAIT_OBJECT_0)
|
||||
if (wait_rc >= WAIT_OBJECT_0 &&
|
||||
(wait_rc <= WAIT_OBJECT_0 + num_handles - 1)) {
|
||||
tv.tv_usec = 0;
|
||||
handle_signaled = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if any sockets have signaled
|
||||
*/
|
||||
rc = select(0, &rfds, &wfds, &efds, &tv);
|
||||
if (rc == SOCKET_ERROR) {
|
||||
if (!handle_signaled && rc == SOCKET_ERROR)
|
||||
return wsa_select_errno(WSAGetLastError());
|
||||
}
|
||||
|
||||
if (wait_rc >= WAIT_OBJECT_0 || (num_sockets && rc > 0))
|
||||
if (handle_signaled || (num_sockets && rc > 0))
|
||||
break;
|
||||
|
||||
timespent_ms += looptime_ms;
|
||||
@ -305,14 +300,14 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
|
||||
|
||||
rc = 0;
|
||||
num_handles = 0;
|
||||
num_fds = 0;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
pfds[i].revents = 0;
|
||||
|
||||
if ((int)pfds[i].fd < 0)
|
||||
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].events, &rfds, &wfds, &efds);
|
||||
|
||||
@ -323,8 +318,6 @@ poll(struct pollfd *pfds, nfds_t nfds, int timeout_ms)
|
||||
num_handles++;
|
||||
}
|
||||
|
||||
num_fds++;
|
||||
|
||||
if (pfds[i].revents)
|
||||
rc++;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user