* child_info.h (cygheap_exec_info::sigmask): Declare new field.

* cygheap.cc (init_cygheap::find_tls): Rename threadlist_ix -> ix.  Only take
one pass through thread list, looking for eligible threads to signal.  Set a
new param indicating that function has found a sigwait* mask.
* cygheap.h (init_cygheap::find_tls): Reflect new parameter.
* dcrt0.cc (parent_sigmask): New variable.
(child_info_spawn::handle_spawn): Save parent's signal mask here.
(dll_crt0_1): Restore parent's signal mask to tls sigmask as appropriate.  Call
sig_dispatch_pending to flush signal queue when we can finally do something
with signals.
* exceptions.cc (sigpacket::process): Avoid attempting to handle signals if we
haven't finished initializing.  Rely on the fact that find_tls will do mask
checking and don't do it again.  Delete ill-named 'dummy' variable.
* sigproc.cc (cygheap_exec_info::alloc): Save calling thread's signal mask in
new sigmask field.
(wait_sig): Try to debug when WFSO fails and DEBUGGING is defined.
* thread.cc (pthread::set_tls_self_pointer): Make this a true automatic method
rather than inexplicably relying on a thread parameter.
(pthread::thread_init_wrapper): Accommodate set_tls_self_pointer change to
non-static.  Initialize sigmask before setting tid or suffer signal races.
* ehread.h (pthread::set_tls_self_pointer): Make non-static, delete parameter.
This commit is contained in:
Christopher Faylor
2013-03-31 12:35:44 +00:00
parent 4332090c2d
commit 8f8eeb70ba
10 changed files with 111 additions and 62 deletions

View File

@ -1124,12 +1124,19 @@ signal_exit (int sig, siginfo_t *si)
int __stdcall
sigpacket::process ()
{
bool continue_now;
struct sigaction dummy = global_sigs[SIGSTOP];
int rc = 1;
bool issig_wait = false;
bool continue_now = false;
struct sigaction& thissig = global_sigs[si.si_signo];
void *handler = have_execed ? NULL : (void *) thissig.sa_handler;
if (si.si_signo != SIGCONT)
continue_now = false;
else
if (!cygwin_finished_initializing)
{
rc = -1;
goto really_done;
}
if (si.si_signo == SIGCONT)
{
continue_now = ISSTATE (myself, PID_STOPPED);
myself->stopsig = 0;
@ -1141,30 +1148,43 @@ sigpacket::process ()
sig_clear (SIGTTOU);
}
int rc = 1;
sigproc_printf ("signal %d processing", si.si_signo);
struct sigaction& thissig = global_sigs[si.si_signo];
myself->rusage_self.ru_nsignals++;
_cygtls *tls;
if (sigtls)
if (!sigtls)
{
tls = sigtls;
sigproc_printf ("using sigtls %p", sigtls);
tls = cygheap->find_tls (si.si_signo, issig_wait);
sigproc_printf ("using tls %p", tls);
}
else
{
tls = cygheap->find_tls (si.si_signo);
sigproc_printf ("using tls %p", tls);
tls = sigtls;
if (sigismember (&tls->sigwait_mask, si.si_signo))
issig_wait = true;
else if (!sigismember (&tls->sigmask, si.si_signo))
issig_wait = false;
else
tls = NULL;
}
if (!tls || ISSTATE (myself, PID_STOPPED))
{
sigproc_printf ("signal %d blocked", si.si_signo);
rc = -1;
goto done;
}
/* Do stuff for gdb */
if ((HANDLE) *tls)
tls->signal_debugger (si);
void *handler = have_execed ? NULL : (void *) thissig.sa_handler;
if (issig_wait)
{
tls->sigwait_mask = 0;
goto dosig;
}
if (handler == SIG_IGN)
{
@ -1180,18 +1200,6 @@ sigpacket::process ()
goto stop;
}
if (sigismember (&tls->sigwait_mask, si.si_signo))
{
tls->sigwait_mask = 0;
goto dosig;
}
if (sigismember (&tls->sigmask, si.si_signo) || ISSTATE (myself, PID_STOPPED))
{
sigproc_printf ("signal %d blocked", si.si_signo);
rc = -1;
goto done;
}
/* Clear pending SIGCONT on stop signals */
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
sig_clear (SIGCONT);
@ -1218,7 +1226,7 @@ sigpacket::process ()
stop:
handler = (void *) sig_handle_tty_stop;
thissig = dummy;
thissig = global_sigs[SIGSTOP];
goto dosig;
exit_sig:
@ -1248,9 +1256,10 @@ dispatch_sig:
done:
if (continue_now)
{
tls->sig = SIGCONT;
(tls ?: _main_tls)->sig = SIGCONT;
SetEvent (tls->signal_arrived);
}
really_done:
sigproc_printf ("returning %d", rc);
return rc;