diff options
author | Niklas Hambüchen <mail@nh2.me> | 2017-09-19 15:10:00 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2017-09-19 15:58:45 -0400 |
commit | c2a1fa7aec426727be6df79f3db109183e42cfdc (patch) | |
tree | 969c9ddaf8e9374d7e3a827142e1c30244feeed0 /libraries/base/cbits | |
parent | 28a115e5e2c3c19b860545f1fcde4317bac3ee2a (diff) | |
download | haskell-c2a1fa7aec426727be6df79f3db109183e42cfdc.tar.gz |
base: Fix fdReady() potentially running forever on Windows.
This fixes #13497 for Windows -- at least for the `if (isSock)` part; I
haven't investigated the case where it's not a socket yet.
Solved by copying the new current-time based waiting logic from the
non-Windows implementation above.
Reviewers: bgamari, austin, hvr
Reviewed By: bgamari
Subscribers: rwbarton, thomie
Differential Revision: https://phabricator.haskell.org/D3954
Diffstat (limited to 'libraries/base/cbits')
-rw-r--r-- | libraries/base/cbits/inputReady.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/libraries/base/cbits/inputReady.c b/libraries/base/cbits/inputReady.c index dbfdb28b70..14f1c546c2 100644 --- a/libraries/base/cbits/inputReady.c +++ b/libraries/base/cbits/inputReady.c @@ -21,10 +21,6 @@ int fdReady(int fd, int write, int msecs, int isSock) { - -#if !defined(_WIN32) - struct pollfd fds[1]; - // if we need to track the time then record the end time in case we are // interrupted. Time endTime = 0; @@ -32,6 +28,9 @@ fdReady(int fd, int write, int msecs, int isSock) endTime = getProcessElapsedTime() + MSToTime(msecs); } +#if !defined(_WIN32) + struct pollfd fds[1]; + fds[0].fd = fd; fds[0].events = write ? POLLOUT : POLLIN; fds[0].revents = 0; @@ -59,7 +58,8 @@ fdReady(int fd, int write, int msecs, int isSock) if (isSock) { int maxfd, ready; fd_set rfd, wfd; - struct timeval tv; + struct timeval remaining_tv; + if ((fd >= (int)FD_SETSIZE) || (fd < 0)) { fprintf(stderr, "fdReady: fd is too big"); abort(); @@ -76,12 +76,22 @@ fdReady(int fd, int write, int msecs, int isSock) * (maxfd-1) */ maxfd = fd + 1; - tv.tv_sec = msecs / 1000; - tv.tv_usec = (msecs % 1000) * 1000; - while ((ready = select(maxfd, &rfd, &wfd, NULL, &tv)) < 0 ) { - if (errno != EINTR ) { - return -1; + Time remaining = MSToTime(msecs); + remaining_tv.tv_sec = TimeToMS(remaining) / 1000; + remaining_tv.tv_usec = TimeToUS(remaining) % 1000000; + + while ((ready = select(maxfd, &rfd, &wfd, NULL, &remaining_tv)) < 0 ) { + if (errno == EINTR) { + if (msecs > 0) { + Time now = getProcessElapsedTime(); + if (now >= endTime) return 0; + remaining = endTime - now; + remaining_tv.tv_sec = TimeToMS(remaining) / 1000; + remaining_tv.tv_usec = TimeToUS(remaining) % 1000000; + } + } else { + return (-1); } } |