https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=66dc7d731aaefb79efda7181bffd81abdc7d5413

commit 66dc7d731aaefb79efda7181bffd81abdc7d5413
Author: Corinna Vinschen <cori...@vinschen.de>
Date:   Sun Mar 20 21:59:27 2016 +0100

    Revert "Improve and simplify select()."
    
    This reverts commit 472d0a228c56bd4783ebb0561667cda2de3cd168.
    
    Revert accidental push

Diff:
---
 winsup/cygwin/cygwait.h | 27 +++++++++++++++++++++
 winsup/cygwin/select.cc | 63 +++++++++++++++++++++++++++++++++++++------------
 winsup/cygwin/select.h  |  1 +
 3 files changed, 76 insertions(+), 15 deletions(-)

diff --git a/winsup/cygwin/cygwait.h b/winsup/cygwin/cygwait.h
index 1240f54..3e02cdd 100644
--- a/winsup/cygwin/cygwait.h
+++ b/winsup/cygwin/cygwait.h
@@ -59,3 +59,30 @@ cygwait (DWORD howlong)
 {
   return cygwait (NULL, howlong);
 }
+
+extern inline DWORD __attribute__ ((always_inline))
+cygwait_us (HANDLE h, LONGLONG howlong, unsigned mask)
+{
+  LARGE_INTEGER li_howlong;
+  PLARGE_INTEGER pli_howlong;
+  if (howlong < 0LL)
+    pli_howlong = NULL;
+  else
+    {
+      li_howlong.QuadPart = -(10LL * howlong);
+      pli_howlong = &li_howlong;
+    }
+  return cygwait (h, pli_howlong, mask);
+}
+
+static inline DWORD __attribute__ ((always_inline))
+cygwait_us (HANDLE h, LONGLONG howlong = -1)
+{
+  return cygwait_us (h, howlong, cw_cancel | cw_sig);
+}
+
+static inline DWORD __attribute__ ((always_inline))
+cygwait_us (LONGLONG howlong)
+{
+  return cygwait_us (NULL, howlong);
+}
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 556a79f..25b0c5a 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -32,6 +32,7 @@ details. */
 #include "pinfo.h"
 #include "sigproc.h"
 #include "cygtls.h"
+#include "cygwait.h"
 
 /*
  * All these defines below should be in sys/types.h
@@ -155,7 +156,7 @@ static int
 select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
        LONGLONG us)
 {
-  select_stuff::wait_states wait_state = select_stuff::select_set_zero;
+  select_stuff::wait_states wait_state = select_stuff::select_loop;
   int ret = 0;
 
   /* Record the current time for later use. */
@@ -181,7 +182,30 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, 
fd_set *exceptfds,
          }
       select_printf ("sel.always_ready %d", sel.always_ready);
 
-      if (sel.always_ready || us == 0)
+      /* Degenerate case.  No fds to wait for.  Just wait for time to run out
+        or signal to arrive. */
+      if (sel.start.next == NULL)
+       switch (cygwait_us (us))
+         {
+         case WAIT_SIGNALED:
+           select_printf ("signal received");
+           /* select() is always interrupted by a signal so set EINTR,
+              unconditionally, ignoring any SA_RESTART detection by
+              call_signal_handler().  */
+           _my_tls.call_signal_handler ();
+           set_sig_errno (EINTR);
+           wait_state = select_stuff::select_signalled;
+           break;
+         case WAIT_CANCELED:
+           sel.destroy ();
+           pthread::static_cancel_self ();
+           /*NOTREACHED*/
+         default:
+           /* Set wait_state to zero below. */
+           wait_state = select_stuff::select_set_zero;
+           break;
+         }
+      else if (sel.always_ready || us == 0)
        /* Catch any active fds via sel.poll() below */
        wait_state = select_stuff::select_ok;
       else
@@ -190,24 +214,29 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, 
fd_set *exceptfds,
 
       select_printf ("sel.wait returns %d", wait_state);
 
-      if (wait_state == select_stuff::select_ok)
+      if (wait_state >= select_stuff::select_ok)
        {
          UNIX_FD_ZERO (readfds, maxfds);
          UNIX_FD_ZERO (writefds, maxfds);
          UNIX_FD_ZERO (exceptfds, maxfds);
-         /* Set bit mask from sel records.  This also sets ret to the
-            right value >= 0, matching the number of bits set in the
-            fds records.  if ret is 0, continue to loop. */
-         ret = sel.poll (readfds, writefds, exceptfds);
-         if (!ret)
-           wait_state = select_stuff::select_set_zero;
+         if (wait_state == select_stuff::select_set_zero)
+           ret = 0;
+         else
+           {
+             /* Set bit mask from sel records.  This also sets ret to the
+                right value >= 0, matching the number of bits set in the
+                fds records.  if ret is 0, continue to loop. */
+             ret = sel.poll (readfds, writefds, exceptfds);
+             if (!ret)
+               wait_state = select_stuff::select_loop;
+           }
        }
       /* Always clean up everything here.  If we're looping then build it
         all up again.  */
       sel.cleanup ();
       sel.destroy ();
-      /* Check and recalculate timeout. */
-      if (us != -1LL && wait_state == select_stuff::select_set_zero)
+      /* Recalculate time remaining to wait if we are going to be looping. */
+      if (wait_state == select_stuff::select_loop && us != -1)
        {
          select_printf ("recalculating us");
          LONGLONG now = gtod.usecs ();
@@ -229,7 +258,7 @@ select (int maxfds, fd_set *readfds, fd_set *writefds, 
fd_set *exceptfds,
            }
        }
     }
-  while (wait_state == select_stuff::select_set_zero);
+  while (wait_state == select_stuff::select_loop);
 
   if (wait_state < select_stuff::select_ok)
     ret = -1;
@@ -465,7 +494,7 @@ next_while:;
         to wait for.  */
     default:
       s = &start;
-      res = select_set_zero;
+      bool gotone = false;
       /* Some types of objects (e.g., consoles) wake up on "inappropriate"
         events like mouse movements.  The verify function will detect these
         situations.  If it returns false, then this wakeup was a false alarm
@@ -479,9 +508,13 @@ next_while:;
          }
        else if ((((wait_ret >= m && s->windows_handle) || s->h == 
w4[wait_ret]))
                 && s->verify (s, readfds, writefds, exceptfds))
-         res = select_ok;
+         gotone = true;
 
-      select_printf ("res after verify %d", res);
+      if (!gotone)
+       res = select_loop;
+      else
+       res = select_ok;
+      select_printf ("gotone %d", gotone);
       break;
     }
 out:
diff --git a/winsup/cygwin/select.h b/winsup/cygwin/select.h
index 3c749ad..581ee4e 100644
--- a/winsup/cygwin/select.h
+++ b/winsup/cygwin/select.h
@@ -78,6 +78,7 @@ public:
   enum wait_states
   {
     select_signalled = -3,
+    select_loop = -2,
     select_error = -1,
     select_ok = 0,
     select_set_zero = 1

Reply via email to