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
|
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++;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user