Fix race condition when waiting for a signal
* cygtls.h (_cygtls::wait_signal_arrived): Renamed from set_signal_arrived. (_cygtls::set_signal_arrived): New function signalling signal_arrived. (_cygtls::reset_signal_arrived): Don't reset will_wait_for_signal. (_cygtls::unwait_signal_arrived): New function only resetting will_wait_for_signal. (class wait_signal_arrived): Rename from set_signal_arrived. Accommodate name change throughout Cygwin. (wait_signal_arrived::~wait_signal_arrived): Call _cygtls::unwait_signal_arrived. Add comment. * cygserver_ipc.h (ipc_set_proc_info): Fetch signal_arrived handle via call to _cygtls::get_signal_arrived. * exceptions.cc (_cygtls::interrupt_setup): Signal signal_arrived via call to _cygtls::set_signal_arrived. (_cygtls::handle_SIGCONT): Ditto. * fhandler_socket.cc (fhandler_socket::wait_for_events): Generate WSAEVENT array prior to entering wait loop. Add cancel event object if available. Remove calls to pthread_testcancel and just call pthread::static_cancel_self if the cancel event object is signalled. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
@ -748,6 +748,12 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
|
||||
int ret;
|
||||
long events = 0;
|
||||
|
||||
WSAEVENT ev[3] = { wsock_evt, NULL, NULL };
|
||||
wait_signal_arrived here (ev[1]);
|
||||
DWORD ev_cnt = 2;
|
||||
if ((ev[2] = pthread::get_cancel_event ()) != NULL)
|
||||
++ev_cnt;
|
||||
|
||||
while (!(ret = evaluate_events (event_mask, events, !(flags & MSG_PEEK)))
|
||||
&& !events)
|
||||
{
|
||||
@ -757,14 +763,9 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
WSAEVENT ev[2] = { wsock_evt };
|
||||
set_signal_arrived here (ev[1]);
|
||||
switch (WSAWaitForMultipleEvents (2, ev, FALSE, 50, FALSE))
|
||||
switch (WSAWaitForMultipleEvents (ev_cnt, ev, FALSE, 50, FALSE))
|
||||
{
|
||||
case WSA_WAIT_TIMEOUT:
|
||||
pthread_testcancel ();
|
||||
break;
|
||||
|
||||
case WSA_WAIT_EVENT_0:
|
||||
break;
|
||||
|
||||
@ -774,8 +775,11 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
|
||||
WSASetLastError (WSAEINTR);
|
||||
return SOCKET_ERROR;
|
||||
|
||||
case WSA_WAIT_EVENT_0 + 2:
|
||||
pthread::static_cancel_self ();
|
||||
break;
|
||||
|
||||
default:
|
||||
pthread_testcancel ();
|
||||
/* wsock_evt can be NULL. We're generating the same errno values
|
||||
as for sockets on which shutdown has been called. */
|
||||
if (WSAGetLastError () != WSA_INVALID_HANDLE)
|
||||
|
Reference in New Issue
Block a user