diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2017-05-12 15:34:59 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2017-05-12 15:34:59 +0000 |
commit | 396a0d4455e4d5438eb1d309a118aa85a1f8e647 (patch) | |
tree | 447487a2f4a3d7dada77f554e4807a24a1f27a87 /sys/kern | |
parent | 342b8b88ba0766330012185207b57cfded73abc9 (diff) | |
download | src-396a0d4455e4d5438eb1d309a118aa85a1f8e647.tar.gz src-396a0d4455e4d5438eb1d309a118aa85a1f8e647.zip |
Do not wake up sleeping thread in reschedule_signals() if the signal
is blocked. The spurious wakeup might result in spurious EINTR.
The reschedule_signals() function is called when the calling thread
has the signal mask changed. For each newly blocked signal, we try to
find a thread which might have the signal not blocked. If no such
thread exists, sigtd() returns random thread, which must not be waken
up. I decided that re-checking, as suggested by PR submitter, is more
reasonable change than to change sigtd() interface, due to other uses
of sigtd(). signotify() already performs this check.
Submitted by: Duane <parakleta@darkreality.org>
PR: 219228
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Notes
Notes:
svn path=/head/; revision=318243
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_sig.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5dfba379e19d..d2596985090e 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2646,7 +2646,9 @@ reschedule_signals(struct proc *p, sigset_t block, int flags) signotify(td); if (!(flags & SIGPROCMASK_PS_LOCKED)) mtx_lock(&ps->ps_mtx); - if (p->p_flag & P_TRACED || SIGISMEMBER(ps->ps_sigcatch, sig)) + if (p->p_flag & P_TRACED || + (SIGISMEMBER(ps->ps_sigcatch, sig) && + !SIGISMEMBER(td->td_sigmask, sig))) tdsigwakeup(td, sig, SIG_CATCH, (SIGISMEMBER(ps->ps_sigintr, sig) ? EINTR : ERESTART)); |