kpsignal2: do not start process (when it is stopped) for all termination
signals (i.e. SA_KILL), just if SIGKILL (or SIGCONT). Improve comments. Make some functions static, remove unused sigrealloc() prototype. Fixes PR/39814. Similar patch reviewed by <ad>.
This commit is contained in:
parent
96c07171a0
commit
be5c9950c6
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: kern_sig.c,v 1.296 2009/03/27 10:58:38 drochner Exp $ */
|
||||
/* $NetBSD: kern_sig.c,v 1.297 2009/03/29 05:02:46 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
@ -66,7 +66,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.296 2009/03/27 10:58:38 drochner Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.297 2009/03/29 05:02:46 rmind Exp $");
|
||||
|
||||
#include "opt_ptrace.h"
|
||||
#include "opt_compat_sunos.h"
|
||||
@ -106,13 +106,11 @@ __KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.296 2009/03/27 10:58:38 drochner Exp
|
||||
|
||||
static void ksiginfo_exechook(struct proc *, void *);
|
||||
static void proc_stop_callout(void *);
|
||||
|
||||
int sigunwait(struct proc *, const ksiginfo_t *);
|
||||
void sigput(sigpend_t *, struct proc *, ksiginfo_t *);
|
||||
int sigpost(struct lwp *, sig_t, int, int, int);
|
||||
int sigchecktrace(void);
|
||||
void sigswitch(bool, int, int);
|
||||
void sigrealloc(ksiginfo_t *);
|
||||
static int sigchecktrace(void);
|
||||
static int sigpost(struct lwp *, sig_t, int, int, int);
|
||||
static void sigput(sigpend_t *, struct proc *, ksiginfo_t *);
|
||||
static int sigunwait(struct proc *, const ksiginfo_t *);
|
||||
static void sigswitch(bool, int, int);
|
||||
|
||||
sigset_t contsigmask, stopsigmask, sigcantmask;
|
||||
static pool_cache_t sigacts_cache; /* memory pool for sigacts structures */
|
||||
@ -551,7 +549,7 @@ out:
|
||||
*
|
||||
* Append a new ksiginfo element to the list of pending ksiginfo's.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
sigput(sigpend_t *sp, struct proc *p, ksiginfo_t *ksi)
|
||||
{
|
||||
ksiginfo_t *kp;
|
||||
@ -883,10 +881,11 @@ kpgsignal(struct pgrp *pgrp, ksiginfo_t *ksi, void *data, int checkctty)
|
||||
KASSERT(!cpu_intr_p());
|
||||
KASSERT(mutex_owned(proc_lock));
|
||||
|
||||
if (pgrp)
|
||||
LIST_FOREACH(p, &pgrp->pg_members, p_pglist)
|
||||
if (checkctty == 0 || p->p_lflag & PL_CONTROLT)
|
||||
kpsignal(p, ksi, data);
|
||||
if (__predict_false(pgrp == 0))
|
||||
return;
|
||||
LIST_FOREACH(p, &pgrp->pg_members, p_pglist)
|
||||
if (checkctty == 0 || p->p_lflag & PL_CONTROLT)
|
||||
kpsignal(p, ksi, data);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1037,7 +1036,7 @@ sigismasked(struct lwp *l, int sig)
|
||||
* Post a pending signal to an LWP. Returns non-zero if the LWP may
|
||||
* be able to take the signal.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
sigpost(struct lwp *l, sig_t action, int prop, int sig, int idlecheck)
|
||||
{
|
||||
int rv, masked;
|
||||
@ -1069,13 +1068,14 @@ sigpost(struct lwp *l, sig_t action, int prop, int sig, int idlecheck)
|
||||
}
|
||||
|
||||
/*
|
||||
* SIGCONT can be masked, but must always restart stopped LWPs.
|
||||
* SIGCONT can be masked, but if LWP is stopped, it needs restart.
|
||||
* Note: SIGKILL and SIGSTOP cannot be masked.
|
||||
*/
|
||||
#if KERN_SA
|
||||
if (p->p_sa != NULL)
|
||||
masked = sigismember(&p->p_sa->sa_sigmask, sig);
|
||||
else
|
||||
#endif /* KERN_SA */
|
||||
#endif
|
||||
masked = sigismember(&l->l_sigmask, sig);
|
||||
if (masked && ((prop & SA_CONT) == 0 || l->l_stat != LSSTOP)) {
|
||||
lwp_unlock(l);
|
||||
@ -1173,7 +1173,7 @@ signotify(struct lwp *l)
|
||||
* Find an LWP within process p that is waiting on signal ksi, and hand
|
||||
* it on.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
sigunwait(struct proc *p, const ksiginfo_t *ksi)
|
||||
{
|
||||
struct lwp *l;
|
||||
@ -1388,8 +1388,6 @@ kpsignal2(struct proc *p, ksiginfo_t *ksi)
|
||||
*/
|
||||
if ((prop & SA_CONT) != 0 && action == SIG_DFL)
|
||||
goto out;
|
||||
|
||||
sigput(&p->p_sigpend, p, kp);
|
||||
} else {
|
||||
/*
|
||||
* Process is stopped or stopping. If traced, then no
|
||||
@ -1398,7 +1396,10 @@ kpsignal2(struct proc *p, ksiginfo_t *ksi)
|
||||
if ((p->p_slflag & PSL_TRACED) != 0 && signo != SIGKILL)
|
||||
goto out;
|
||||
|
||||
if ((prop & (SA_CONT | SA_KILL)) != 0) {
|
||||
/*
|
||||
* Run the process only if sending SIGCONT or SIGKILL.
|
||||
*/
|
||||
if ((prop & SA_CONT) != 0 || signo == SIGKILL) {
|
||||
/*
|
||||
* Re-adjust p_nstopchild if the process wasn't
|
||||
* collected by its parent.
|
||||
@ -1409,27 +1410,28 @@ kpsignal2(struct proc *p, ksiginfo_t *ksi)
|
||||
p->p_pptr->p_nstopchild--;
|
||||
|
||||
/*
|
||||
* If SIGCONT is default (or ignored), we continue
|
||||
* the process but don't leave the signal in
|
||||
* ps_siglist, as it has no further action. If
|
||||
* SIGCONT is held, we continue the process and
|
||||
* leave the signal in ps_siglist. If the process
|
||||
* catches SIGCONT, let it handle the signal itself.
|
||||
* If it isn't waiting on an event, then it goes
|
||||
* back to run state. Otherwise, process goes back
|
||||
* to sleep state.
|
||||
* Do not make signal pending if SIGCONT is default.
|
||||
*
|
||||
* If the process catches SIGCONT, let it handle the
|
||||
* signal itself (if waiting on event - process runs,
|
||||
* otherwise continues sleeping).
|
||||
*/
|
||||
if ((prop & SA_CONT) == 0 || action != SIG_DFL)
|
||||
sigput(&p->p_sigpend, p, kp);
|
||||
if ((prop & SA_CONT) != 0 && action == SIG_DFL) {
|
||||
KASSERT(signo != SIGKILL);
|
||||
goto deliver;
|
||||
}
|
||||
} else if ((prop & SA_STOP) != 0) {
|
||||
/*
|
||||
* Already stopped, don't need to stop again.
|
||||
* (If we did the shell could get confused.)
|
||||
*/
|
||||
goto out;
|
||||
} else
|
||||
sigput(&p->p_sigpend, p, kp);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Make signal pending.
|
||||
*/
|
||||
sigput(&p->p_sigpend, p, kp);
|
||||
|
||||
deliver:
|
||||
/*
|
||||
@ -1594,7 +1596,7 @@ proc_stop_done(struct proc *p, bool ppsig, int ppmask)
|
||||
/*
|
||||
* Stop the current process and switch away when being stopped or traced.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
sigswitch(bool ppsig, int ppmask, int signo)
|
||||
{
|
||||
struct lwp *l = curlwp;
|
||||
@ -1660,7 +1662,7 @@ sigswitch(bool ppsig, int ppmask, int signo)
|
||||
/*
|
||||
* Check for a signal from the debugger.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
sigchecktrace(void)
|
||||
{
|
||||
struct lwp *l = curlwp;
|
||||
|
Loading…
Reference in New Issue
Block a user