summaryrefslogtreecommitdiff
path: root/libraries/base/cbits
diff options
context:
space:
mode:
authorNiklas Hambüchen <mail@nh2.me>2017-09-19 15:10:00 -0400
committerBen Gamari <ben@smart-cactus.org>2017-09-19 15:58:45 -0400
commitc2a1fa7aec426727be6df79f3db109183e42cfdc (patch)
tree969c9ddaf8e9374d7e3a827142e1c30244feeed0 /libraries/base/cbits
parent28a115e5e2c3c19b860545f1fcde4317bac3ee2a (diff)
downloadhaskell-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.c30
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);
}
}