* sigproc.cc (pending_signals::retry): Declare new element.

(pending_signals::pending): Force an additional loop through wait_sig by
setting retry whenever this function is called.
(sig_send): Reorganize to wait for SIGHOLD at bottom.  Always add signal to
pending queue and work on whole queue rather than just the one signal.  Loop
when sigq.retry is set.  Fix long-broken check for SIGCHLD after queued
signals.
This commit is contained in:
Christopher Faylor 2013-03-29 01:22:14 +00:00
parent 1a863e04b3
commit 5e31c80e4e
2 changed files with 32 additions and 41 deletions

View File

@ -1,3 +1,13 @@
2013-03-28 Christopher Faylor <me.cygwin2013@cgf.cx>
* sigproc.cc (pending_signals::retry): Declare new element.
(pending_signals::pending): Force an additional loop through wait_sig
by setting retry whenever this function is called.
(sig_send): Reorganize to wait for SIGHOLD at bottom. Always add
signal to pending queue and work on whole queue rather than just the
one signal. Loop when sigq.retry is set. Fix long-broken check for
SIGCHLD after queued signals.
2013-03-28 Christopher Faylor <me.cygwin2013@cgf.cx> 2013-03-28 Christopher Faylor <me.cygwin2013@cgf.cx>
* exceptions.cc (exception::handle): Generalize comment. * exceptions.cc (exception::handle): Generalize comment.

View File

@ -76,11 +76,12 @@ class pending_signals
sigpacket *end; sigpacket *end;
sigpacket *prev; sigpacket *prev;
sigpacket *curr; sigpacket *curr;
bool retry;
public: public:
void reset () {curr = &start; prev = &start;} void reset () {curr = &start; prev = &start;}
void add (sigpacket&); void add (sigpacket&);
void del (); void del ();
bool pending () const {return !!start.next;} bool pending () {retry = true; return !!start.next;}
sigpacket *next (); sigpacket *next ();
sigpacket *save () const {return curr;} sigpacket *save () const {return curr;}
void restore (sigpacket *saved) {curr = saved;} void restore (sigpacket *saved) {curr = saved;}
@ -627,7 +628,8 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
} }
} }
sigproc_printf ("sendsig %p, pid %d, signal %d, its_me %d", sendsig, p->pid, si.si_signo, its_me); sigproc_printf ("sendsig %p, pid %d, signal %d, its_me %d", sendsig, p->pid,
si.si_signo, its_me);
sigset_t pending; sigset_t pending;
if (!its_me) if (!its_me)
@ -1231,9 +1233,9 @@ void
pending_signals::add (sigpacket& pack) pending_signals::add (sigpacket& pack)
{ {
sigpacket *se; sigpacket *se;
if (sigs[pack.si.si_signo].si.si_signo)
return;
se = sigs + pack.si.si_signo; se = sigs + pack.si.si_signo;
if (se->si.si_signo)
return;
*se = pack; *se = pack;
se->mask = &pack.sigtls->sigmask; se->mask = &pack.sigtls->sigmask;
se->next = NULL; se->next = NULL;
@ -1281,18 +1283,17 @@ wait_sig (VOID *)
sigproc_printf ("entering ReadFile loop, my_readsig %p, my_sendsig %p", sigproc_printf ("entering ReadFile loop, my_readsig %p, my_sendsig %p",
my_readsig, my_sendsig); my_readsig, my_sendsig);
sigpacket pack;
pack.si.si_signo = 0;
for (;;) for (;;)
{ {
if (pack.si.si_signo == __SIGHOLD)
WaitForSingleObject (sig_hold, INFINITE);
DWORD nb; DWORD nb;
pack.sigtls = NULL; sigpacket pack = {};
if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL)) if (sigq.retry)
break; {
sigq.retry = false;
pack.si.si_signo = __SIGFLUSH;
}
else if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL))
Sleep (INFINITE); /* Never exit this thread */
if (nb != sizeof (pack)) if (nb != sizeof (pack))
{ {
system_printf ("short read from signal pipe: %d != %d", nb, system_printf ("short read from signal pipe: %d != %d", nb,
@ -1340,6 +1341,11 @@ wait_sig (VOID *)
case __SIGHOLD: case __SIGHOLD:
goto loop; goto loop;
break; break;
default:
if (pack.si.si_signo < 0)
sig_clear (-pack.si.si_signo);
else
sigq.add (pack);
case __SIGNOHOLD: case __SIGNOHOLD:
case __SIGFLUSH: case __SIGFLUSH:
case __SIGFLUSHFAST: case __SIGFLUSHFAST:
@ -1349,7 +1355,7 @@ wait_sig (VOID *)
int sig = q->si.si_signo; int sig = q->si.si_signo;
if (sig == __SIGDELETE || q->process () > 0) if (sig == __SIGDELETE || q->process () > 0)
sigq.del (); sigq.del ();
if (sig == __SIGNOHOLD && q->si.si_signo == SIGCHLD) if (sig == SIGCHLD)
clearwait = true; clearwait = true;
} }
break; break;
@ -1373,33 +1379,6 @@ wait_sig (VOID *)
system_printf ("WaitForSingleObject(%p) for thread exit returned %u", h, res); system_printf ("WaitForSingleObject(%p) for thread exit returned %u", h, res);
} }
break; break;
default:
if (pack.si.si_signo < 0)
sig_clear (-pack.si.si_signo);
else
{
int sig = pack.si.si_signo;
// FIXME: REALLY not right when taking threads into consideration.
// We need a per-thread queue since each thread can have its own
// list of blocked signals. CGF 2005-08-24
if (sigq.sigs[sig].si.si_signo && sigq.sigs[sig].sigtls == pack.sigtls)
sigproc_printf ("signal %d already queued", pack.si.si_signo);
else
{
int sigres = pack.process ();
if (sigres <= 0)
{
#ifdef DEBUGGING2
if (!sigres)
system_printf ("Failed to arm signal %d from pid %d", pack.si.si_signo, pack.pid);
#endif
sigq.add (pack); // FIXME: Shouldn't add this in !sh condition
}
}
if (sig == SIGCHLD)
clearwait = true;
}
break;
} }
if (clearwait && !have_execed) if (clearwait && !have_execed)
proc_subproc (PROC_CLEARWAIT, 0); proc_subproc (PROC_CLEARWAIT, 0);
@ -1409,5 +1388,7 @@ wait_sig (VOID *)
sigproc_printf ("signalling pack.wakeup %p", pack.wakeup); sigproc_printf ("signalling pack.wakeup %p", pack.wakeup);
SetEvent (pack.wakeup); SetEvent (pack.wakeup);
} }
if (pack.si.si_signo == __SIGHOLD)
WaitForSingleObject (sig_hold, INFINITE);
} }
} }