Re-evaluate thread' signal mask after ptracestop().

The stop drops process lock, which allows the signal mask to be
changed and our selected signal might become blocked, i.e. should be
returned to the process queue instead of delivery.

Also, for the existing check of the process no longer having an
attached debugger, we should not loose the signal, but requeue it.

Reported and tested by:	bdrewery
Reviewed by:	jhb
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2017-10-16 20:21:51 +00:00
parent cd735d8f5a
commit e9445808a8

View File

@ -2855,15 +2855,32 @@ issignal(struct thread *td)
mtx_lock(&ps->ps_mtx); mtx_lock(&ps->ps_mtx);
/* /*
* Keep looking if the debugger discarded the signal * Keep looking if the debugger discarded or
* or replaced it with a masked signal. * replaced the signal.
*
* If the traced bit got turned off, go back up
* to the top to rescan signals. This ensures
* that p_sig* and p_sigact are consistent.
*/ */
if (sig == 0 || (p->p_flag & P_TRACED) == 0) if (sig == 0)
continue; continue;
/*
* If the signal became masked, re-queue it.
*/
if (SIGISMEMBER(td->td_sigmask, sig)) {
ksi.ksi_flags |= KSI_HEAD;
sigqueue_add(&p->p_sigqueue, sig, &ksi);
continue;
}
/*
* If the traced bit got turned off, requeue
* the signal and go back up to the top to
* rescan signals. This ensures that p_sig*
* and p_sigact are consistent.
*/
if ((p->p_flag & P_TRACED) == 0) {
ksi.ksi_flags |= KSI_HEAD;
sigqueue_add(queue, sig, &ksi);
continue;
}
} }
prop = sigprop(sig); prop = sigprop(sig);