[commit: ghc] master: base: Fix fdReady() potentially running forever on Windows. (c2a1fa7)

git at git.haskell.org git at git.haskell.org
Tue Sep 19 21:55:31 UTC 2017


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/c2a1fa7aec426727be6df79f3db109183e42cfdc/ghc

>---------------------------------------------------------------

commit c2a1fa7aec426727be6df79f3db109183e42cfdc
Author: Niklas Hambüchen <mail at nh2.me>
Date:   Tue Sep 19 15:10:00 2017 -0400

    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


>---------------------------------------------------------------

c2a1fa7aec426727be6df79f3db109183e42cfdc
 libraries/base/cbits/inputReady.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/libraries/base/cbits/inputReady.c b/libraries/base/cbits/inputReady.c
index dbfdb28..14f1c54 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);
             }
         }
 



More information about the ghc-commits mailing list