4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-28 03:27:46 +08:00

* 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.
This commit is contained in:
Corinna Vinschen 2011-05-03 15:58:52 +00:00
parent 3728c79d48
commit 781822a646
4 changed files with 51 additions and 10 deletions

View File

@ -1,3 +1,13 @@
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> 2011-05-03 Corinna Vinschen <corinna@vinschen.de>
* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Make * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Make

View 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. */ /* Degenerate case. No fds to wait for. Just wait. */
if (sel.start.next == NULL) 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"); select_printf ("signal received");
set_sig_errno (EINTR); set_sig_errno (EINTR);
return -1; return -1;
case WAIT_OBJECT_0 + 1:
sel.destroy ();
pthread::static_cancel_self ();
/*NOTREACHED*/
default:
break;
} }
timeout = 1; timeout = 1;
} }
@ -193,9 +203,9 @@ select_stuff::cleanup ()
} }
/* Destroy all storage associated with select stuff. */ /* Destroy all storage associated with select stuff. */
select_stuff::~select_stuff () inline void
select_stuff::destroy ()
{ {
cleanup ();
select_record *s = &start; select_record *s = &start;
select_record *snext = start.next; 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 */ /* Add a record to the select chain */
bool bool
select_stuff::test_and_set (int i, fd_set *readfds, fd_set *writefds, 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; select_record *s = &start;
int m = 0; int m = 0;
int res = 0; int res = 0;
bool is_cancelable = false;
w4[m++] = signal_arrived; /* Always wait for the arrival of a signal. */ 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 /* Loop through the select chain, starting up anything appropriate and
counting the number of active fds. */ counting the number of active fds. */
while ((s = s->next)) 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 the problem that the call to PeekMessage disarms the queue state
so that a subsequent MWFMO hangs, even if there are still messages so that a subsequent MWFMO hangs, even if there are still messages
in the queue. */ in the queue. */
wait_ret = wait_ret = MsgWaitForMultipleObjectsEx (m, w4, ms,
MsgWaitForMultipleObjectsEx (m, w4, ms, QS_ALLINPUT | QS_ALLPOSTMESSAGE,
QS_ALLINPUT | QS_ALLPOSTMESSAGE, MWMO_INPUTAVAILABLE);
MWMO_INPUTAVAILABLE);
switch (wait_ret) switch (wait_ret)
{ {
@ -304,6 +326,14 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_printf ("signal received"); select_printf ("signal received");
set_sig_errno (EINTR); set_sig_errno (EINTR);
return -1; return -1;
case WAIT_OBJECT_0 + 1:
if (is_cancelable)
{
cleanup ();
destroy ();
pthread::static_cancel_self ();
}
break;
case WAIT_FAILED: case WAIT_FAILED:
cleanup (); cleanup ();
system_printf ("WaitForMultipleObjects failed"); system_printf ("WaitForMultipleObjects failed");

View File

@ -83,6 +83,7 @@ public:
int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds); int poll (fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms); int wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds, DWORD ms);
void cleanup (); void cleanup ();
void destroy ();
select_stuff (): always_ready (0), windows_used (0), start (0), select_stuff (): always_ready (0), windows_used (0), start (0),
device_specific_pipe (0), device_specific_pipe (0),
device_specific_socket (0), device_specific_socket (0),

View File

@ -597,9 +597,9 @@ pthread::cancel ()
* open () * open ()
* openat () * openat ()
* pause () * pause ()
poll () * poll ()
* pread () * pread ()
pselect () * pselect ()
* pthread_cond_timedwait () * pthread_cond_timedwait ()
* pthread_cond_wait () * pthread_cond_wait ()
* pthread_join () * pthread_join ()
@ -612,7 +612,7 @@ pthread::cancel ()
* recv () * recv ()
* recvfrom () * recvfrom ()
* recvmsg () * recvmsg ()
select () * select ()
* sem_timedwait () * sem_timedwait ()
* sem_wait () * sem_wait ()
* send () * send ()