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:
Corinna Vinschen
2015-11-27 14:39:11 +01:00
parent 9471b0b36d
commit c43e9340f1
12 changed files with 63 additions and 26 deletions

View File

@@ -248,7 +248,7 @@ public:
}
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;
@@ -258,10 +258,17 @@ public:
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 ();
@@ -430,14 +437,18 @@ public:
}
#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)