OSDN Git Service

* select.cc (cygwin_select): Make degenerate case cancelable.
authorcorinna <corinna>
Tue, 3 May 2011 15:58:51 +0000 (15:58 +0000)
committercorinna <corinna>
Tue, 3 May 2011 15:58:51 +0000 (15:58 +0000)
(select_stuff::destroy): New inline method to delete memory taken
by select_stuff.
(select_stuff::~select_stuff): Call destroy.
(select_stuff::wait): Add case to allow canceling select.
* select.h (select_stuff::destroy): Declare.
* thread.cc: Mark poll, pselect and poll as cancelable.

winsup/cygwin/ChangeLog
winsup/cygwin/select.cc
winsup/cygwin/select.h
winsup/cygwin/thread.cc

index 330bd81..b348b12 100644 (file)
@@ -1,5 +1,15 @@
 2011-05-03  Corinna Vinschen  <corinna@vinschen.de>
 
+       * select.cc (cygwin_select): Make degenerate case cancelable.
+       (select_stuff::destroy): New inline method to delete memory taken
+       by select_stuff.
+       (select_stuff::~select_stuff): Call destroy.
+       (select_stuff::wait): Add case to allow canceling select.
+       * select.h (select_stuff::destroy): Declare.
+       * thread.cc: Mark poll, pselect and poll as cancelable.
+
+2011-05-03  Corinna Vinschen  <corinna@vinschen.de>
+
        * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Make
        cancelable.  Remove test for main thread, always add signal_arrived
        to waited objects.
index 6c093a0..fd0281f 100644 (file)
@@ -133,11 +133,21 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
   /* Degenerate case.  No fds to wait for.  Just wait. */
   if (sel.start.next == NULL)
     {
-      if (WaitForSingleObject (signal_arrived, ms) == WAIT_OBJECT_0)
+      HANDLE w4[2] = { signal_arrived, pthread::get_cancel_event () };
+      DWORD cnt = w4[1] ? 2 : 1;
+
+      switch (WaitForMultipleObjects (cnt, w4, FALSE, ms))
        {
+       case WAIT_OBJECT_0:
          select_printf ("signal received");
          set_sig_errno (EINTR);
          return -1;
+       case WAIT_OBJECT_0 + 1:
+         sel.destroy ();
+         pthread::static_cancel_self ();
+         /*NOTREACHED*/
+       default:
+         break;
        }
       timeout = 1;
     }
@@ -193,9 +203,9 @@ select_stuff::cleanup ()
 }
 
 /* Destroy all storage associated with select stuff. */
-select_stuff::~select_stuff ()
+inline void
+select_stuff::destroy ()
 {
-  cleanup ();
   select_record *s = &start;
   select_record *snext = start.next;
 
@@ -207,6 +217,12 @@ select_stuff::~select_stuff ()
     }
 }
 
+select_stuff::~select_stuff ()
+{
+  cleanup ();
+  destroy ();
+}
+
 /* Add a record to the select chain */
 bool
 select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds,
@@ -254,8 +270,15 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
   select_record *s = &start;
   int m = 0;
   int res = 0;
+  bool is_cancelable = false;
 
   w4[m++] = signal_arrived;  /* Always wait for the arrival of a signal. */
+  if ((w4[m] = pthread::get_cancel_event ()) != NULL)
+    {
+      ++m;
+      is_cancelable = true;
+    }
+
   /* Loop through the select chain, starting up anything appropriate and
      counting the number of active fds. */
   while ((s = s->next))
@@ -292,10 +315,9 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
           the problem that the call to PeekMessage disarms the queue state
           so that a subsequent MWFMO hangs, even if there are still messages
           in the queue. */
-       wait_ret =
-         MsgWaitForMultipleObjectsEx (m, w4, ms,
-                                      QS_ALLINPUT | QS_ALLPOSTMESSAGE,
-                                      MWMO_INPUTAVAILABLE);
+       wait_ret = MsgWaitForMultipleObjectsEx (m, w4, ms,
+                                               QS_ALLINPUT | QS_ALLPOSTMESSAGE,
+                                               MWMO_INPUTAVAILABLE);
 
       switch (wait_ret)
       {
@@ -304,6 +326,14 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
          select_printf ("signal received");
          set_sig_errno (EINTR);
          return -1;
+       case WAIT_OBJECT_0 + 1:
+         if (is_cancelable)
+           {
+             cleanup ();
+             destroy ();
+             pthread::static_cancel_self ();
+           }
+         break;
        case WAIT_FAILED:
          cleanup ();
          system_printf ("WaitForMultipleObjects failed");
index 8734b1e..2f5434b 100644 (file)
@@ -83,6 +83,7 @@ public:
   int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
   int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
   void cleanup ();
+  void destroy ();
   select_stuff (): always_ready (0), windows_used (0), start (0),
                   device_specific_pipe (0),
                   device_specific_socket (0),
index 0085320..a521773 100644 (file)
@@ -597,9 +597,9 @@ pthread::cancel ()
     * open ()
     * openat ()
     * pause ()
-      poll ()
+    * poll ()
     * pread ()
-      pselect ()
+    * pselect ()
     * pthread_cond_timedwait ()
     * pthread_cond_wait ()
     * pthread_join ()
@@ -612,7 +612,7 @@ pthread::cancel ()
     * recv ()
     * recvfrom ()
     * recvmsg ()
-      select ()
+    * select ()
     * sem_timedwait ()
     * sem_wait ()
     * send ()