Fix a bug relavant to debugging, a masked signal unexpectedly interrupts

a sleeping thread when process is being debugged.

PR: GNU/77818
Tested by: Sean C. Farley <sean-freebsd at farley org>
This commit is contained in:
David Xu 2005-06-06 05:13:10 +00:00
parent 96d8846397
commit ec8297bda1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147046

View file

@ -1690,34 +1690,25 @@ do_tdsignal(struct thread *td, int sig, sigtarget_t target)
}
/*
* If proc is traced, always give parent a chance;
* if signal event is tracked by procfs, give *that*
* a chance, as well.
* If the signal is being ignored,
* then we forget about it immediately.
* (Note: we don't set SIGCONT in ps_sigignore,
* and if it is set to SIG_IGN,
* action will be SIG_DFL here.)
*/
if ((p->p_flag & P_TRACED) || (p->p_stops & S_SIG)) {
action = SIG_DFL;
} else {
/*
* If the signal is being ignored,
* then we forget about it immediately.
* (Note: we don't set SIGCONT in ps_sigignore,
* and if it is set to SIG_IGN,
* action will be SIG_DFL here.)
*/
mtx_lock(&ps->ps_mtx);
if (SIGISMEMBER(ps->ps_sigignore, sig) ||
(p->p_flag & P_WEXIT)) {
mtx_unlock(&ps->ps_mtx);
return;
}
if (SIGISMEMBER(td->td_sigmask, sig))
action = SIG_HOLD;
else if (SIGISMEMBER(ps->ps_sigcatch, sig))
action = SIG_CATCH;
else
action = SIG_DFL;
mtx_lock(&ps->ps_mtx);
if (SIGISMEMBER(ps->ps_sigignore, sig) ||
(p->p_flag & P_WEXIT)) {
mtx_unlock(&ps->ps_mtx);
return;
}
if (SIGISMEMBER(td->td_sigmask, sig))
action = SIG_HOLD;
else if (SIGISMEMBER(ps->ps_sigcatch, sig))
action = SIG_CATCH;
else
action = SIG_DFL;
mtx_unlock(&ps->ps_mtx);
if (prop & SA_CONT) {
SIG_STOPSIGMASK(p->p_siglist);
@ -1866,14 +1857,16 @@ do_tdsignal(struct thread *td, int sig, sigtarget_t target)
* Mutexes are short lived. Threads waiting on them will
* hit thread_suspend_check() soon.
*/
} else if (p->p_state == PRS_NORMAL) {
if ((p->p_flag & P_TRACED) || (action != SIG_DFL) ||
!(prop & SA_STOP)) {
} else if (p->p_state == PRS_NORMAL) {
if (p->p_flag & P_TRACED || action == SIG_CATCH) {
mtx_lock_spin(&sched_lock);
tdsigwakeup(td, sig, action);
mtx_unlock_spin(&sched_lock);
goto out;
}
MPASS(action == SIG_DFL);
if (prop & SA_STOP) {
if (p->p_flag & P_PPWAIT)
goto out;
@ -1959,34 +1952,26 @@ tdsigwakeup(struct thread *td, int sig, sig_t action)
if ((td->td_flags & TDF_SINTR) == 0)
return;
/*
* Process is sleeping and traced. Make it runnable
* so it can discover the signal in issignal() and stop
* for its parent.
* If SIGCONT is default (or ignored) and process is
* asleep, we are finished; the process should not
* be awakened.
*/
if (p->p_flag & P_TRACED) {
p->p_flag &= ~P_STOPPED_TRACE;
} else {
if ((prop & SA_CONT) && action == SIG_DFL) {
SIGDELSET(p->p_siglist, sig);
/*
* If SIGCONT is default (or ignored) and process is
* asleep, we are finished; the process should not
* be awakened.
* It may be on either list in this state.
* Remove from both for now.
*/
if ((prop & SA_CONT) && action == SIG_DFL) {
SIGDELSET(p->p_siglist, sig);
/*
* It may be on either list in this state.
* Remove from both for now.
*/
SIGDELSET(td->td_siglist, sig);
return;
}
/*
* Give low priority threads a better chance to run.
*/
if (td->td_priority > PUSER)
sched_prio(td, PUSER);
SIGDELSET(td->td_siglist, sig);
return;
}
/*
* Give low priority threads a better chance to run.
*/
if (td->td_priority > PUSER)
sched_prio(td, PUSER);
sleepq_abort(td);
} else {
/*