give a better error message in the non-threaded RTS for out-of-range FDs
[ghc-hetmet.git] / rts / posix / Select.c
index ccf3945..0127b3c 100644 (file)
@@ -6,18 +6,20 @@
  *
  * ---------------------------------------------------------------------------*/
 
-/* we're outside the realms of POSIX here... */
-/* #include "PosixSource.h" */
-
+#include "PosixSource.h"
 #include "Rts.h"
+
+#include "Signals.h"
 #include "Schedule.h"
 #include "RtsUtils.h"
-#include "RtsFlags.h"
-#include "Timer.h"
 #include "Itimer.h"
-#include "Signals.h"
 #include "Capability.h"
-#include "posix/Select.h"
+#include "Select.h"
+#include "AwaitEvent.h"
+
+# ifdef HAVE_SYS_SELECT_H
+#  include <sys/select.h>
+# endif
 
 # ifdef HAVE_SYS_TYPES_H
 #  include <sys/types.h>
@@ -59,12 +61,18 @@ wakeUpSleepingThreads(lnat ticks)
     StgTSO *tso;
     rtsBool flag = rtsFalse;
 
-    while (sleeping_queue != END_TSO_QUEUE &&
-          (int)(ticks - sleeping_queue->block_info.target) > 0) {
+    while (sleeping_queue != END_TSO_QUEUE) {
        tso = sleeping_queue;
-       sleeping_queue = tso->link;
+        if (tso->what_next == ThreadRelocated) {
+            sleeping_queue = tso->_link;
+            continue;
+        }
+        if (((long)ticks - (long)tso->block_info.target) < 0) {
+            break;
+        }
+       sleeping_queue = tso->_link;
        tso->why_blocked = NotBlocked;
-       tso->link = END_TSO_QUEUE;
+       tso->_link = END_TSO_QUEUE;
        IF_DEBUG(scheduler,debugBelch("Waking up sleeping thread %lu\n", (unsigned long)tso->id));
        // MainCapability: this code is !THREADED_RTS
        pushOnRunQueue(&MainCapability,tso);
@@ -73,6 +81,13 @@ wakeUpSleepingThreads(lnat ticks)
     return flag;
 }
 
+static void GNUC3_ATTRIBUTE(__noreturn__)
+fdOutOfRange (int fd)
+{
+    errorBelch("file descriptor %d out of range for select (0--%d).\nRecompile with -threaded to work around this.", fd, (int)FD_SETSIZE);
+    stg_exit(EXIT_FAILURE);
+}
+
 /* Argument 'wait' says whether to wait for I/O to become available,
  * or whether to just check and return immediately.  If there are
  * other threads ready to run, we normally do the non-waiting variety,
@@ -138,14 +153,18 @@ awaitEvent(rtsBool wait)
       FD_ZERO(&wfd);
 
       for(tso = blocked_queue_hd; tso != END_TSO_QUEUE; tso = next) {
-       next = tso->link;
+       next = tso->_link;
 
+      /* On FreeBSD FD_SETSIZE is unsigned. Cast it to signed int
+       * in order to switch off the 'comparison between signed and
+       * unsigned error message
+       */
        switch (tso->why_blocked) {
        case BlockedOnRead:
          { 
            int fd = tso->block_info.fd;
-           if (fd >= FD_SETSIZE) {
-               barf("awaitEvent: descriptor out of range");
+           if ((fd >= (int)FD_SETSIZE) || (fd < 0)) {
+                fdOutOfRange(fd);
            }
            maxfd = (fd > maxfd) ? fd : maxfd;
            FD_SET(fd, &rfd);
@@ -155,8 +174,8 @@ awaitEvent(rtsBool wait)
        case BlockedOnWrite:
          { 
            int fd = tso->block_info.fd;
-           if (fd >= FD_SETSIZE) {
-               barf("awaitEvent: descriptor out of range");
+           if ((fd >= (int)FD_SETSIZE) || (fd < 0)) {
+                fdOutOfRange(fd);
            }
            maxfd = (fd > maxfd) ? fd : maxfd;
            FD_SET(fd, &wfd);
@@ -207,7 +226,7 @@ awaitEvent(rtsBool wait)
           * serviced.
           */
 #if defined(RTS_USER_SIGNALS)
-         if (signals_pending()) {
+         if (RtsFlags.MiscFlags.install_signal_handlers && signals_pending()) {
              startSignalHandlers(&MainCapability);
              return; /* still hold the lock */
          }
@@ -238,7 +257,12 @@ awaitEvent(rtsBool wait)
       prev = NULL;
       if (select_succeeded || unblock_all) {
          for(tso = blocked_queue_hd; tso != END_TSO_QUEUE; tso = next) {
-             next = tso->link;
+             next = tso->_link;
+
+              if (tso->what_next == ThreadRelocated) {
+                  continue;
+              }
+
              switch (tso->why_blocked) {
              case BlockedOnRead:
                  ready = unblock_all || FD_ISSET(tso->block_info.fd, &rfd);
@@ -253,13 +277,13 @@ awaitEvent(rtsBool wait)
              if (ready) {
                IF_DEBUG(scheduler,debugBelch("Waking up blocked thread %lu\n", (unsigned long)tso->id));
                  tso->why_blocked = NotBlocked;
-                 tso->link = END_TSO_QUEUE;
+                 tso->_link = END_TSO_QUEUE;
                  pushOnRunQueue(&MainCapability,tso);
              } else {
                  if (prev == NULL)
                      blocked_queue_hd = tso;
                  else
-                     prev->link = tso;
+                     setTSOLink(&MainCapability, prev, tso);
                  prev = tso;
              }
          }
@@ -267,7 +291,7 @@ awaitEvent(rtsBool wait)
          if (prev == NULL)
              blocked_queue_hd = blocked_queue_tl = END_TSO_QUEUE;
          else {
-             prev->link = END_TSO_QUEUE;
+             prev->_link = END_TSO_QUEUE;
              blocked_queue_tl = prev;
          }
       }
@@ -277,3 +301,4 @@ awaitEvent(rtsBool wait)
 }
 
 #endif /* THREADED_RTS */
+