Fix SA_SIGINFO | SA_RESETHAND handling. The sysent' sv_sendsig()
method needs pre-reset state of the ps_siginfo to correctly construct signal frame. Move sigdflt() call after the sv_sendsig() invocation in postsig(). Simultaneously extract common code from trapsignal() and postsig() into new helper postsig_done(). Submitted by: rea MFC after: 1 week
This commit is contained in:
parent
315a4d6fb4
commit
e442f29f08
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=275120
@ -1882,6 +1882,30 @@ pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Recalculate the signal mask and reset the signal disposition after
|
||||
* usermode frame for delivery is formed. Should be called after
|
||||
* mach-specific routine, because sysent->sv_sendsig() needs correct
|
||||
* ps_siginfo and signal mask.
|
||||
*/
|
||||
static void
|
||||
postsig_done(int sig, struct thread *td, struct sigacts *ps)
|
||||
{
|
||||
sigset_t mask;
|
||||
|
||||
mtx_assert(&ps->ps_mtx, MA_OWNED);
|
||||
td->td_ru.ru_nsignals++;
|
||||
mask = ps->ps_catchmask[_SIG_IDX(sig)];
|
||||
if (!SIGISMEMBER(ps->ps_signodefer, sig))
|
||||
SIGADDSET(mask, sig);
|
||||
kern_sigprocmask(td, SIG_BLOCK, &mask, NULL,
|
||||
SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED);
|
||||
if (SIGISMEMBER(ps->ps_sigreset, sig))
|
||||
sigdflt(ps, sig);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Send a signal caused by a trap to the current thread. If it will be
|
||||
* caught immediately, deliver it with correct code. Otherwise, post it
|
||||
@ -1891,7 +1915,6 @@ void
|
||||
trapsignal(struct thread *td, ksiginfo_t *ksi)
|
||||
{
|
||||
struct sigacts *ps;
|
||||
sigset_t mask;
|
||||
struct proc *p;
|
||||
int sig;
|
||||
int code;
|
||||
@ -1906,7 +1929,6 @@ trapsignal(struct thread *td, ksiginfo_t *ksi)
|
||||
mtx_lock(&ps->ps_mtx);
|
||||
if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(ps->ps_sigcatch, sig) &&
|
||||
!SIGISMEMBER(td->td_sigmask, sig)) {
|
||||
td->td_ru.ru_nsignals++;
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(curthread, KTR_PSIG))
|
||||
ktrpsig(sig, ps->ps_sigact[_SIG_IDX(sig)],
|
||||
@ -1914,13 +1936,7 @@ trapsignal(struct thread *td, ksiginfo_t *ksi)
|
||||
#endif
|
||||
(*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)],
|
||||
ksi, &td->td_sigmask);
|
||||
mask = ps->ps_catchmask[_SIG_IDX(sig)];
|
||||
if (!SIGISMEMBER(ps->ps_signodefer, sig))
|
||||
SIGADDSET(mask, sig);
|
||||
kern_sigprocmask(td, SIG_BLOCK, &mask, NULL,
|
||||
SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED);
|
||||
if (SIGISMEMBER(ps->ps_sigreset, sig))
|
||||
sigdflt(ps, sig);
|
||||
postsig_done(sig, td, ps);
|
||||
mtx_unlock(&ps->ps_mtx);
|
||||
} else {
|
||||
/*
|
||||
@ -2802,7 +2818,7 @@ postsig(sig)
|
||||
struct sigacts *ps;
|
||||
sig_t action;
|
||||
ksiginfo_t ksi;
|
||||
sigset_t returnmask, mask;
|
||||
sigset_t returnmask;
|
||||
|
||||
KASSERT(sig != 0, ("postsig"));
|
||||
|
||||
@ -2857,20 +2873,12 @@ postsig(sig)
|
||||
} else
|
||||
returnmask = td->td_sigmask;
|
||||
|
||||
mask = ps->ps_catchmask[_SIG_IDX(sig)];
|
||||
if (!SIGISMEMBER(ps->ps_signodefer, sig))
|
||||
SIGADDSET(mask, sig);
|
||||
kern_sigprocmask(td, SIG_BLOCK, &mask, NULL,
|
||||
SIGPROCMASK_PROC_LOCKED | SIGPROCMASK_PS_LOCKED);
|
||||
|
||||
if (SIGISMEMBER(ps->ps_sigreset, sig))
|
||||
sigdflt(ps, sig);
|
||||
td->td_ru.ru_nsignals++;
|
||||
if (p->p_sig == sig) {
|
||||
p->p_code = 0;
|
||||
p->p_sig = 0;
|
||||
}
|
||||
(*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask);
|
||||
postsig_done(sig, td, ps);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user