+2015-11-27 Corinna Vinschen <corinna@vinschen.de>
+
+ * 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.
+
2015-11-26 Corinna Vinschen <corinna@vinschen.de>
* path.cc (symlink_native): Fix index when looking for colon in path.
blk.gidcnt = 0;
blk.gidlist = NULL;
blk.is_admin = false;
- if (in_fork)
- blk.signal_arrived = NULL;
- else
- _my_tls.set_signal_arrived (true, blk.signal_arrived);
+ blk.signal_arrived = in_fork ? NULL : _my_tls.get_signal_arrived (true);
}
#endif /* __INSIDE_CYGWIN__ */
/* cygthread.cc
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009,
- 2010, 2011, 2012, 2013 Red Hat, Inc.
+ 2010, 2011, 2012, 2013, 2015 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
unsigned n = 2;
DWORD howlong = INFINITE;
w4[0] = sigwait;
- set_signal_arrived here (w4[1]);
+ wait_signal_arrived here (w4[1]);
/* For a description of the below loop see the end of this file */
for (int i = 0; i < 2; i++)
switch (res = WaitForMultipleObjects (n, w4, FALSE, howlong))
}
return signal_arrived;
}
- void set_signal_arrived (bool setit, HANDLE& h)
+ void wait_signal_arrived (bool setit, HANDLE& h)
{
if (!setit)
will_wait_for_signal = false;
will_wait_for_signal = true;
}
}
+ void set_signal_arrived ()
+ {
+ SetEvent (get_signal_arrived (false));
+ }
void reset_signal_arrived ()
{
if (signal_arrived)
ResetEvent (signal_arrived);
+ }
+ void unwait_signal_arrived ()
+ {
will_wait_for_signal = false;
}
void handle_SIGCONT ();
}
#endif /* __x86_64__ */
-class set_signal_arrived
+class wait_signal_arrived
{
public:
- set_signal_arrived (bool setit, HANDLE& h) { _my_tls.set_signal_arrived (setit, h); }
- set_signal_arrived (HANDLE& h) { _my_tls.set_signal_arrived (true, h); }
+ wait_signal_arrived (bool setit, HANDLE& h) { _my_tls.wait_signal_arrived (setit, h); }
+ wait_signal_arrived (HANDLE& h) { _my_tls.wait_signal_arrived (true, h); }
operator int () const {return _my_tls.will_wait_for_signal;}
- ~set_signal_arrived () { _my_tls.reset_signal_arrived (); }
+ /* Do not reset the signal_arrived event just because we leave the scope of
+ this wait_signal_arrived object. This may lead to all sorts of races.
+ The only method actually resetting the signal_arrived event is
+ _cygtls::call_signal_handler. */
+ ~wait_signal_arrived () { _my_tls.unwait_signal_arrived (); }
};
#define __getreent() (&_my_tls.local_clib)
if (object)
wait_objects[num++] = object;
- set_signal_arrived thread_waiting (is_cw_sig_handle, wait_objects[num]);
+ wait_signal_arrived thread_waiting (is_cw_sig_handle, wait_objects[num]);
debug_only_printf ("object %p, thread waiting %d, signal_arrived %p", object, (int) thread_waiting, _my_tls.signal_arrived);
DWORD sig_n;
if (!thread_waiting)
this->sig = si.si_signo; /* Should always be last thing set to avoid race */
if (incyg)
- SetEvent (get_signal_arrived (false));
+ set_signal_arrived ();
if (!have_execed)
proc_subproc (PROC_CLEARWAIT, 1);
else
{
sig = SIGCONT;
- SetEvent (signal_arrived); /* alert sig_handle_tty_stop */
+ set_signal_arrived (); /* alert sig_handle_tty_stop */
sigsent = true;
}
/* Clear pending stop signals */
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)
{
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;
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)
/* fhandler_windows.cc: code to access windows message queues.
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2011, 2012,
- 2013 Red Hat, Inc.
+ 2013, 2015 Red Hat, Inc.
Written by Sergey S. Okhapkin (sos@prospect.com.ru).
Feedback and testing by Andy Piper (andyp@parallax.co.uk).
}
HANDLE w4[2];
- set_signal_arrived here (w4[0]);
+ wait_signal_arrived here (w4[0]);
DWORD cnt = 1;
if ((w4[1] = pthread::get_cancel_event ()) != NULL)
++cnt;
timeout = 100L;
DWORD WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + wait_count;
- set_signal_arrived here (w4[wait_count++]);
+ wait_signal_arrived here (w4[wait_count++]);
DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1;
HANDLE cancel_event = pthread::get_cancel_event ();
DWORD timer_idx = 0;
int ret = 0;
- set_signal_arrived here (w4[1]);
+ wait_signal_arrived here (w4[1]);
if ((w4[cnt] = pthread::get_cancel_event ()) != NULL)
++cnt;
if (abstime)
- Replaced old, buggy strtold implementation with well-tested gdtoa version
from David M. Gay.
Addresses: https://cygwin.com/ml/cygwin/2015-11/msg00205.html
+
+- Fix a race condition in signal handling.
+ Addresses: https://cygwin.com/ml/cygwin/2015-11/msg00387.html
select_record *s = &start;
DWORD m = 0;
- set_signal_arrived here (w4[m++]);
+ wait_signal_arrived here (w4[m++]);
if ((w4[m] = pthread::get_cancel_event ()) != NULL)
m++;