Finding #4

This code didn't build, it could probably be removed.

Philippe
===

Fix: fix the parenthesis; limit the timeout to INT_MAX milliseconds as
the poll() version does; add descriptors through a new selectFd(),
which refuses (and reports once) those outside 0 to FD_SETSIZE-1 and
keeps track of the highest one; pass inputFd + 1 in +awakenedBefore:;
fix a format string (NSInteger printed with %d).

---

diff --git a/Source/unix/GSRunLoopCtxt.m b/Source/unix/GSRunLoopCtxt.m
index 3b4496410..d9d572eb1 100644
--- a/Source/unix/GSRunLoopCtxt.m
+++ b/Source/unix/GSRunLoopCtxt.m
@@ -723,6 +723,35 @@ static void setPollfd(int fd, int event, GSRunLoopCtxtUnix 
*ctxt)
 
 #else
 
+/* Add fd to the set and update the highest descriptor seen.  A
+ * descriptor outside 0 to FD_SETSIZE-1 cannot be watched by select():
+ * FD_SET() would write outside the set, so it is refused (and reported
+ * once).
+ */
+static BOOL
+selectFd(int fd, fd_set *set, int *fdEnd)
+{
+  if (fd < 0 || fd >= FD_SETSIZE)
+    {
+      static BOOL      warned = NO;
+
+      if (NO == warned && fd >= 0)
+       {
+         warned = YES;
+         NSLog(@"Run loop cannot watch descriptor %d with select()"
+           @" (FD_SETSIZE is %d): ignoring it and any others.",
+           fd, (int)FD_SETSIZE);
+       }
+      return NO;
+    }
+  FD_SET(fd, set);
+  if (fd > *fdEnd)
+    {
+      *fdEnd = fd;
+    }
+  return YES;
+}
+
 - (BOOL) pollUntil: (int64_t)microseconds within: (NSArray*)contexts
 {
   GSRunLoopThreadInfo   *threadInfo = loop->threadInfo;
@@ -735,7 +764,6 @@ static void setPollfd(int fd, int event, GSRunLoopCtxtUnix 
*ctxt)
   fd_set               read_fds;       // Mask for read-ready fds.
   fd_set               exception_fds;  // Mask for exception fds.
   fd_set               write_fds;      // Mask for write-ready fds.
-  int                  fd;
   int                  fdEnd = -1;
   unsigned             count;
   unsigned             i;
@@ -780,18 +808,12 @@ static void setPollfd(int fd, int event, 
GSRunLoopCtxtUnix *ctxt)
 
   /* Watch for signals from other threads.
    */
-  fd = threadInfo->inputFd;
-  if (fd > fdEnd)
-    fdEnd = fd;
-  FD_SET (fd, &read_fds);
+  selectFd(threadInfo->inputFd, &read_fds, &fdEnd);
 #if GS_USE_LIBDISPATCH_RUNLOOP
   if (loop->isMainThread && loop->dispatchHandle != NULL
     && (loop->commonModeMask & (UINT64_C(1) << modeIndex)))
     {
-      fd = (int)(intptr_t)loop->dispatchHandle;
-      if (fd > fdEnd)
-       fdEnd = fd;
-      FD_SET (fd, &read_fds);
+      selectFd((int)(intptr_t)loop->dispatchHandle, &read_fds, &fdEnd);
     }
 #endif
 
@@ -836,26 +858,26 @@ static void setPollfd(int fd, int event, 
GSRunLoopCtxtUnix *ctxt)
            {
              case ET_EDESC: 
                fd = (int)(intptr_t)info->data;
-               if (fd > fdEnd)
-                 fdEnd = fd;
-               FD_SET (fd, &exception_fds);
-               NSMapInsert(_efdMap, (void*)(intptr_t)fd, info);
+               if (selectFd(fd, &exception_fds, &fdEnd))
+                 {
+                   NSMapInsert(_efdMap, (void*)(intptr_t)fd, info);
+                 }
                break;
 
              case ET_RDESC: 
                fd = (int)(intptr_t)info->data;
-               if (fd > fdEnd)
-                 fdEnd = fd;
-               FD_SET (fd, &read_fds);
-               NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
+               if (selectFd(fd, &read_fds, &fdEnd))
+                 {
+                   NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
+                 }
                break;
 
              case ET_WDESC: 
                fd = (int)(intptr_t)info->data;
-               if (fd > fdEnd)
-                 fdEnd = fd;
-               FD_SET (fd, &write_fds);
-               NSMapInsert(_wfdMap, (void*)(intptr_t)fd, info);
+               if (selectFd(fd, &write_fds, &fdEnd))
+                 {
+                   NSMapInsert(_wfdMap, (void*)(intptr_t)fd, info);
+                 }
                break;
 
              case ET_RPORT: 
@@ -875,15 +897,15 @@ static void setPollfd(int fd, int event, 
GSRunLoopCtxtUnix *ctxt)
                       port_fd_array = malloc(sizeof(NSInteger)*port_fd_size);
                       [port getFds: port_fd_array count: &port_fd_count];
                     }
-                 NSDebugMLLog(@"NSRunLoop", @"listening to %d port sockets",
-                   port_fd_count);
+                 NSDebugMLLog(@"NSRunLoop", @"listening to %ld port sockets",
+                   (long)port_fd_count);
                  while (port_fd_count--)
                    {
                      fd = port_fd_array[port_fd_count];
-                     if (fd > fdEnd)
-                       fdEnd = fd;
-                     FD_SET (fd, &read_fds);
-                     NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
+                     if (selectFd(fd, &read_fds, &fdEnd))
+                       {
+                         NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
+                       }
                    }
                   if (port_fd_array != port_fd_buffer) free(port_fd_array);
                }
@@ -901,7 +923,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxtUnix 
*ctxt)
    * we try an instantaneous select so that, if there is no input pending,
    * we can service the queue.
    */
-  if (GSPrivateCheckTasks() || GSPrivateNotifyMore(mode)) || immediate)
+  if (GSPrivateCheckTasks() || GSPrivateNotifyMore(mode) || immediate)
     {
       microseconds = 0;
     }
@@ -913,6 +935,15 @@ static void setPollfd(int fd, int event, GSRunLoopCtxtUnix 
*ctxt)
       timeout.tv_sec = 0;
       timeout.tv_usec = 0;
     }
+  else if (microseconds / 1000000 >= INT_MAX / 1000)
+    {
+      /* Limit the wait as the poll() version does (to INT_MAX
+       * milliseconds): a larger value would overflow tv_sec, and
+       * select() fails with EINVAL for a negative timeout.
+       */
+      timeout.tv_sec = INT_MAX / 1000;
+      timeout.tv_usec = 0;
+    }
   else
     {
       timeout.tv_sec = (int)(microseconds/1000000);
@@ -1173,7 +1204,10 @@ static void setPollfd(int fd, int event, 
GSRunLoopCtxtUnix *ctxt)
   timeout.tv_sec = milliseconds/1000;
   timeout.tv_usec = (milliseconds - 1000 * timeout.tv_sec) * 1000;
   FD_SET (threadInfo->inputFd, &read_fds);
-  if (select (threadInfo->inputFd, &read_fds, &write_fds,
+  /* The first argument is the number of descriptors to look at,
+   * one more than the highest.
+   */
+  if (select (threadInfo->inputFd + 1, &read_fds, &write_fds,
     &exception_fds, &timeout) > 0)
     {
       NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
-- 
2.39.5

Reply via email to