Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2013-04-09 05:01:19 +0400
committerChristopher Faylor <me@cgf.cx>2013-04-09 05:01:19 +0400
commit9d2155089e8709977ef012cfdfd88d511b92d154 (patch)
treeb2d6845c34da33952996e16a1e637f61268ae351 /winsup/cygwin/sigproc.cc
parent037ad80a525e5be3088bcb3b34546498695e746f (diff)
* cygtls.h (_cygtls::reset_signal_arrived): Actually reset the signal_arrived
event. (_cygtls::handle_SIGCONT): Declare ew function. * cygwait.cc (is_cw_sig_handle): Delete. (is_cw_sig_cont): New convenience define. (cygwait): Clear signal if is_cw_sig_cont and we got a SIGCONT. * cygwait.h (cw_wait_mask): Add cw_sig_cont. * exceptions.cc (sig_handle_tty_stop): Tighten "incyg" region. Use cw_sig_cont param for cygwait. Don't zero signal here outside of lock. (sigpacket::setup_handler): Don't check for in_forkee since we will now never get here in that state. (_cygtls::handle_SIGCONT): Define new function. (sigpacket::process): Call handle_SIGCONT early to deal with SIGCONT. Nuke continue_now handling. Allow SIGKILL to kill a suspended process. Delete a couple of now-unneeded labels. (_cygtls::call_signal_handler): Reorganize setting of incyg within lock. * sigproc.cc (pending_signals): Simplify. (pending_signals::clear): New method. (_cygtls::remove_wq): Reorganize to always close wq.thread_ev if it exists to avoid handle leaks. (sig_clear): Simplify by just calling sigq.clear(). (sig_dispatch_pending): Always call sigq.pending even in signal thread to force another loop in wait_sig. (sig_send): Remove a "goto out" just before out: label. (pending_signals::add): Simplify. (pending_signals::del): Delete. (pending_signals::next): Delete. (wait_sig): Define variable q to be the start of the signal queue. Just iterate through sigq queue, deleting processed or zeroed signals. Only set clearwait when the current signal is SIGCHLD. * sigproc.h: Add a comment about an unused enum.
Diffstat (limited to 'winsup/cygwin/sigproc.cc')
-rw-r--r--winsup/cygwin/sigproc.cc135
1 files changed, 44 insertions, 91 deletions
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 4bf6f5630..e585877b9 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -73,20 +73,15 @@ class pending_signals
{
sigpacket sigs[NSIG + 1];
sigpacket start;
- sigpacket *end;
- sigpacket *prev;
- sigpacket *curr;
bool retry;
+
public:
- void reset () {curr = &start; prev = &start;}
void add (sigpacket&);
- void del ();
bool pending () {retry = true; return !!start.next;}
- sigpacket *next ();
- sigpacket *save () const {return curr;}
- void restore (sigpacket *saved) {curr = saved;}
+ void clear (int sig) {sigs[sig].si.si_signo = 0;}
friend void __reg1 sig_dispatch_pending (bool);;
friend void WINAPI wait_sig (VOID *arg);
+ friend void sigproc_init ();
};
Static pending_signals sigq;
@@ -338,18 +333,22 @@ out1:
void
_cygtls::remove_wq (DWORD wait)
{
- if (exit_state < ES_FINAL && waitq_head.next && sync_proc_subproc
- && sync_proc_subproc.acquire (wait))
+ if (wq.thread_ev)
{
- for (waitq *w = &waitq_head; w->next != NULL; w = w->next)
- if (w->next == &wq)
- {
- ForceCloseHandle1 (wq.thread_ev, wq_ev);
- w->next = wq.next;
- break;
- }
- sync_proc_subproc.release ();
+ if (exit_state < ES_FINAL && waitq_head.next && sync_proc_subproc
+ && sync_proc_subproc.acquire (wait))
+ {
+ for (waitq *w = &waitq_head; w->next != NULL; w = w->next)
+ if (w->next == &wq)
+ {
+ w->next = wq.next;
+ break;
+ }
+ sync_proc_subproc.release ();
+ }
+ ForceCloseHandle1 (wq.thread_ev, wq_ev);
}
+
}
/* Terminate the wait_subproc thread.
@@ -392,23 +391,9 @@ proc_terminate ()
/* Clear pending signal */
void __reg1
-sig_clear (int target_sig)
+sig_clear (int sig)
{
- if (&_my_tls != _sig_tls)
- sig_send (myself, -target_sig);
- else
- {
- sigpacket *q;
- sigpacket *save = sigq.save ();
- sigq.reset ();
- while ((q = sigq.next ()))
- if (q->si.si_signo == target_sig)
- {
- q->si.si_signo = __SIGDELETE;
- break;
- }
- sigq.restore (save);
- }
+ sigq.clear (sig);
}
extern "C" int
@@ -425,21 +410,10 @@ sigpending (sigset_t *mask)
void __reg1
sig_dispatch_pending (bool fast)
{
- if (&_my_tls == _sig_tls)
- {
-#ifdef DEBUGGING
- sigproc_printf ("exit_state %d, cur thread id %p, _sig_tls %p, sigq.start.next %p",
- exit_state, GetCurrentThreadId (), _sig_tls, sigq.start.next);
-#endif
- return;
- }
-
/* Non-atomically test for any signals pending and wake up wait_sig if any are
found. It's ok if there's a race here since the next call to this function
- should catch it.
- FIXME: Eventually, wait_sig should wake up on its own to deal with pending
- signals. */
- if (sigq.pending ())
+ should catch it. */
+ if (sigq.pending () && &_my_tls != _sig_tls)
sig_send (myself, fast ? __SIGFLUSHFAST : __SIGFLUSH);
}
@@ -728,7 +702,6 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
if (wait_for_completion && si.si_signo != __SIGFLUSHFAST)
_my_tls.call_signal_handler ();
- goto out;
out:
if (communing && rc)
@@ -1232,46 +1205,19 @@ talktome (siginfo_t *si)
new cygthread (commune_process, size, si, "commune");
}
+/* Add a packet to the beginning of the queue.
+ Should only be called from signal thread. */
void
pending_signals::add (sigpacket& pack)
{
sigpacket *se;
+
se = sigs + pack.si.si_signo;
if (se->si.si_signo)
return;
*se = pack;
se->next = NULL;
- if (end)
- end->next = se;
- end = se;
- if (!start.next)
- start.next = se;
-}
-
-void
-pending_signals::del ()
-{
- sigpacket *next = curr->next;
- prev->next = next;
- curr->si.si_signo = 0;
-#ifdef DEBUGGING
- curr->next = NULL;
-#endif
- if (end == curr)
- end = prev;
- curr = next;
-}
-
-sigpacket *
-pending_signals::next ()
-{
- sigpacket *res;
- prev = curr;
- if (!curr || !(curr = curr->next))
- res = NULL;
- else
- res = curr;
- return res;
+ start.next = se;
}
/* Process signals by waiting for signal data to arrive in a pipe.
@@ -1311,7 +1257,7 @@ wait_sig (VOID *)
pack.mask = &dummy_mask;
}
- sigpacket *q;
+ sigpacket *q = &sigq.start;
bool clearwait = false;
switch (pack.si.si_signo)
{
@@ -1324,8 +1270,7 @@ wait_sig (VOID *)
case __SIGPENDING:
*pack.mask = 0;
unsigned bit;
- sigq.reset ();
- while ((q = sigq.next ()))
+ while ((q = q->next))
if (pack.sigtls->sigmask & (bit = SIGTOMASK (q->si.si_signo)))
*pack.mask |= bit;
break;
@@ -1340,15 +1285,23 @@ wait_sig (VOID *)
case __SIGNOHOLD:
case __SIGFLUSH:
case __SIGFLUSHFAST:
- sigq.reset ();
- while ((q = sigq.next ()))
- {
- int sig = q->si.si_signo;
- if (sig == __SIGDELETE || q->process () > 0)
- sigq.del ();
- if (sig == SIGCHLD)
- clearwait = true;
- }
+ {
+ sigpacket *qnext;
+ /* Check the queue for signals. There will always be at least one
+ thing on the queue if this was a valid signal. */
+ while ((qnext = q->next))
+ {
+ if (qnext->si.si_signo && qnext->process () <= 0)
+ q = q->next;
+ else
+ {
+ q->next = qnext->next;
+ qnext->si.si_signo = 0;
+ }
+ }
+ if (pack.si.si_signo == SIGCHLD)
+ clearwait = true;
+ }
break;
case __SIGSETPGRP:
init_console_handler (true);