From e3b7e3352c6bba0bf7b6991e5485264a868e4800 Mon Sep 17 00:00:00 2001
From: Simon Marlow <marlowsd@gmail.com>
Date: Mon, 16 Jan 2012 09:49:24 +0000
Subject: [PATCH] Fix bug causing polling instead of blocking in the
 non-threaded RTS (#5773)

This was a regression introduced accidentally in
6b1098511aaabd2c9503ee7be6da1944466f9cb4.  We were previously passing
a large time value to select() to simulate blocking, and this broke
due to a change from unsigned to signed arithmetic.  I've refactored
it to be less fragile now - we just pass NULL as the timeval parameter
to select(), which is the correct way to do blocking.
---
 rts/posix/Select.c | 35 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/rts/posix/Select.c b/rts/posix/Select.c
index 45737ce0cc9c..ffe72e8933e4 100644
--- a/rts/posix/Select.c
+++ b/rts/posix/Select.c
@@ -118,13 +118,9 @@ awaitEvent(rtsBool wait)
     int maxfd = -1;
     rtsBool select_succeeded = rtsTrue;
     rtsBool unblock_all = rtsFalse;
-    struct timeval tv;
-    Time min;
+    struct timeval tv, *ptv;
     LowResTime now;
 
-    tv.tv_sec  = 0;
-    tv.tv_usec = 0;
-    
     IF_DEBUG(scheduler,
 	     debugBelch("scheduler: checking for threads blocked on I/O");
 	     if (wait) {
@@ -145,15 +141,7 @@ awaitEvent(rtsBool wait)
 	  return;
       }
 
-      if (!wait) {
-	  min = 0;
-      } else if (sleeping_queue != END_TSO_QUEUE) {
-          min = LowResTimeToTime(sleeping_queue->block_info.target - now);
-      } else {
-          min = (Time)-1;
-      }
-
-      /* 
+      /*
        * Collect all of the fd's that we're interested in
        */
       FD_ZERO(&rfd);
@@ -194,12 +182,23 @@ awaitEvent(rtsBool wait)
 	}
       }
 
+      if (wait) {
+          ptv = NULL;
+      } else if (sleeping_queue != END_TSO_QUEUE) {
+          Time min = LowResTimeToTime(sleeping_queue->block_info.target - now);
+          tv.tv_sec  = TimeToSeconds(min);
+          tv.tv_usec = TimeToUS(min) % 1000000;
+          ptv = &tv;
+      } else {
+          // just poll
+          tv.tv_sec  = 0;
+          tv.tv_usec = 0;
+          ptv = &tv;
+      }
+
       /* Check for any interesting events */
       
-      tv.tv_sec  = TimeToSeconds(min);
-      tv.tv_usec = TimeToUS(min) % 1000000;
-
-      while ((numFound = select(maxfd+1, &rfd, &wfd, NULL, &tv)) < 0) {
+      while ((numFound = select(maxfd+1, &rfd, &wfd, NULL, ptv)) < 0) {
 	  if (errno != EINTR) {
 	    /* Handle bad file descriptors by unblocking all the
 	       waiting threads. Why? Because a thread might have been
-- 
GitLab