From 781822a646eb87f01ce47b98dea8fbc7dfc4d177 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 3 May 2011 15:58:52 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 10 ++++++++++ winsup/cygwin/select.cc | 44 ++++++++++++++++++++++++++++++++++------- winsup/cygwin/select.h | 1 + winsup/cygwin/thread.cc | 6 +++--- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 330bd8131..b348b12c8 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2011-05-03 Corinna Vinschen + + * 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 * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Make diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 6c093a06d..fd0281f50 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -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"); diff --git a/winsup/cygwin/select.h b/winsup/cygwin/select.h index 8734b1e04..2f5434bc8 100644 --- a/winsup/cygwin/select.h +++ b/winsup/cygwin/select.h @@ -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), diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 0085320ad..a521773d8 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -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 ()