summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2002-04-13 23:33:36 +0000
committerjhb <jhb@FreeBSD.org>2002-04-13 23:33:36 +0000
commite93a8a367d8e585317af59c94921580daae0fe09 (patch)
treea9af4d93327ab271d1d0f15d79337bfed9dca182 /sys/kern
parent38c9f516335b9581593ecd45940b127c595c80a1 (diff)
downloadFreeBSD-src-e93a8a367d8e585317af59c94921580daae0fe09.zip
FreeBSD-src-e93a8a367d8e585317af59c94921580daae0fe09.tar.gz
- Change killpg1()'s first argument to be a thread instead of a process so
we can use td_ucred. - In killpg1(), the proc lock is sufficient to check if p_stat is SZOMB or not. We don't need sched_lock. - Close some races in psignal(). In psignal() there is a big switch statement based on p_stat. All the different cases are assuming that the process (or thread) isn't going to change state out from under it. To ensure this is true, just lock sched_lock for the entire switch. We practically held it the entire time already anyways. This also simplifies the locking somewhat and actually results in fewer lock operations. - Allow signotify() to be called with the sched_lock held since psignal() now does that. - Use td_ucred in a couple of places.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sig.c58
1 files changed, 22 insertions, 36 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 6adda1d..f64e0ec 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -80,7 +80,7 @@ static int do_sigaction(struct proc *p, int sig, struct sigaction *act,
static int do_sigprocmask(struct proc *p, int how, sigset_t *set,
sigset_t *oset, int old);
static char *expand_name(const char *, uid_t, pid_t);
-static int killpg1(struct proc *cp, int sig, int pgid, int all);
+static int killpg1(struct thread *td, int sig, int pgid, int all);
static int sig_ffs(sigset_t *set);
static int sigprop(int sig);
static void stop(struct proc *);
@@ -190,7 +190,6 @@ signotify(struct proc *p)
{
PROC_LOCK_ASSERT(p, MA_OWNED);
- mtx_assert(&sched_lock, MA_NOTOWNED);
mtx_lock_spin(&sched_lock);
if (SIGPENDING(p)) {
p->p_sflag |= PS_NEEDSIGCHK;
@@ -991,8 +990,8 @@ done2:
* cp is calling process.
*/
int
-killpg1(cp, sig, pgid, all)
- register struct proc *cp;
+killpg1(td, sig, pgid, all)
+ register struct thread *td;
int sig, pgid, all;
{
register struct proc *p;
@@ -1006,11 +1005,12 @@ killpg1(cp, sig, pgid, all)
sx_slock(&allproc_lock);
LIST_FOREACH(p, &allproc, p_list) {
PROC_LOCK(p);
- if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == cp) {
+ if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
+ p == td->td_proc) {
PROC_UNLOCK(p);
continue;
}
- if (p_cansignal(cp, p, sig) == 0) {
+ if (p_cansignal(td->td_proc, p, sig) == 0) {
nfound++;
if (sig)
psignal(p, sig);
@@ -1024,7 +1024,7 @@ killpg1(cp, sig, pgid, all)
/*
* zero pgid means send to my process group.
*/
- pgrp = cp->p_pgrp;
+ pgrp = td->td_proc->p_pgrp;
PGRP_LOCK(pgrp);
} else {
pgrp = pgfind(pgid);
@@ -1040,14 +1040,11 @@ killpg1(cp, sig, pgid, all)
PROC_UNLOCK(p);
continue;
}
- mtx_lock_spin(&sched_lock);
if (p->p_stat == SZOMB) {
- mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
continue;
}
- mtx_unlock_spin(&sched_lock);
- if (p_cansignal(cp, p, sig) == 0) {
+ if (p_cansignal(td->td_proc, p, sig) == 0) {
nfound++;
if (sig)
psignal(p, sig);
@@ -1074,7 +1071,6 @@ kill(td, uap)
register struct thread *td;
register struct kill_args *uap;
{
- register struct proc *cp = td->td_proc;
register struct proc *p;
int error = 0;
@@ -1086,7 +1082,7 @@ kill(td, uap)
/* kill single process */
if ((p = pfind(uap->pid)) == NULL) {
error = ESRCH;
- } else if (p_cansignal(cp, p, uap->signum)) {
+ } else if (p_cansignal(td->td_proc, p, uap->signum)) {
PROC_UNLOCK(p);
error = EPERM;
} else {
@@ -1098,13 +1094,13 @@ kill(td, uap)
} else {
switch (uap->pid) {
case -1: /* broadcast signal */
- error = killpg1(cp, uap->signum, 0, 1);
+ error = killpg1(td, uap->signum, 0, 1);
break;
case 0: /* signal own process group */
- error = killpg1(cp, uap->signum, 0, 0);
+ error = killpg1(td, uap->signum, 0, 0);
break;
default: /* negative explicit process group */
- error = killpg1(cp, uap->signum, -uap->pid, 0);
+ error = killpg1(td, uap->signum, -uap->pid, 0);
break;
}
}
@@ -1133,7 +1129,7 @@ okillpg(td, uap)
if ((u_int)uap->signum > _SIG_MAXSIG)
return (EINVAL);
mtx_lock(&Giant);
- error = killpg1(td->td_proc, uap->signum, uap->pgid, 0);
+ error = killpg1(td, uap->signum, uap->pgid, 0);
mtx_unlock(&Giant);
return (error);
}
@@ -1327,13 +1323,13 @@ psignal(p, sig)
SIG_CONTSIGMASK(p->p_siglist);
}
SIGADDSET(p->p_siglist, sig);
+ mtx_lock_spin(&sched_lock);
signotify(p);
/*
* Defer further processing for signals which are held,
* except that stopped processes must be continued by SIGCONT.
*/
- mtx_lock_spin(&sched_lock);
if (action == SIG_HOLD && (!(prop & SA_CONT) || p->p_stat != SSTOP)) {
mtx_unlock_spin(&sched_lock);
return;
@@ -1348,10 +1344,8 @@ psignal(p, sig)
* be noticed when the process returns through
* trap() or syscall().
*/
- if ((td->td_flags & TDF_SINTR) == 0) {
- mtx_unlock_spin(&sched_lock);
+ if ((td->td_flags & TDF_SINTR) == 0)
goto out;
- }
/*
* Process is sleeping and traced... make it runnable
* so it can discover the signal in issignal() and stop
@@ -1359,7 +1353,6 @@ psignal(p, sig)
*/
if (p->p_flag & P_TRACED)
goto run;
- mtx_unlock_spin(&sched_lock);
/*
* If SIGCONT is default (or ignored) and process is
* asleep, we are finished; the process should not
@@ -1384,6 +1377,7 @@ psignal(p, sig)
*/
if (p->p_flag & P_PPWAIT)
goto out;
+ mtx_unlock_spin(&sched_lock);
SIGDELSET(p->p_siglist, sig);
p->p_xstat = sig;
PROC_LOCK(p->p_pptr);
@@ -1392,14 +1386,12 @@ psignal(p, sig)
PROC_UNLOCK(p->p_pptr);
mtx_lock_spin(&sched_lock);
stop(p);
- mtx_unlock_spin(&sched_lock);
goto out;
} else
goto runfast;
/* NOTREACHED */
case SSTOP:
- mtx_unlock_spin(&sched_lock);
/*
* If traced process is already stopped,
* then no further action is necessary.
@@ -1428,7 +1420,6 @@ psignal(p, sig)
SIGDELSET(p->p_siglist, sig);
if (action == SIG_CATCH)
goto runfast;
- mtx_lock_spin(&sched_lock);
/*
* XXXKSE
* do this for each thread.
@@ -1443,12 +1434,10 @@ psignal(p, sig)
/* mark it as sleeping */
}
}
- mtx_unlock_spin(&sched_lock);
} else {
if (td->td_wchan == NULL)
goto run;
p->p_stat = SSLEEP;
- mtx_unlock_spin(&sched_lock);
}
goto out;
}
@@ -1469,7 +1458,6 @@ psignal(p, sig)
* the process runnable, leave it stopped.
* XXXKSE should we wake ALL blocked threads?
*/
- mtx_lock_spin(&sched_lock);
if (p->p_flag & P_KSES) {
FOREACH_THREAD_IN_PROC(p, td) {
if (td->td_wchan && (td->td_flags & TDF_SINTR)){
@@ -1487,7 +1475,6 @@ psignal(p, sig)
unsleep(td); /* XXXKSE */
}
}
- mtx_unlock_spin(&sched_lock);
goto out;
default:
@@ -1511,7 +1498,6 @@ psignal(p, sig)
}
#endif
}
- mtx_unlock_spin(&sched_lock);
goto out;
}
/*NOTREACHED*/
@@ -1522,7 +1508,6 @@ runfast:
* XXXKSE Should we make them all run fast?
* Maybe just one would be enough?
*/
- mtx_lock_spin(&sched_lock);
if (FIRST_THREAD_IN_PROC(p)->td_priority > PUSER) {
FIRST_THREAD_IN_PROC(p)->td_priority = PUSER;
@@ -1531,9 +1516,10 @@ run:
/* If we jump here, sched_lock has to be owned. */
mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
setrunnable(td); /* XXXKSE */
- mtx_unlock_spin(&sched_lock);
out:
- /* If we jump here, sched_lock should not be owned. */
+ mtx_unlock_spin(&sched_lock);
+
+ /* Once we get here, sched_lock should not be owned. */
mtx_assert(&sched_lock, MA_NOTOWNED);
}
@@ -1861,7 +1847,7 @@ sigexit(td, sig)
log(LOG_INFO,
"pid %d (%s), uid %d: exited on signal %d%s\n",
p->p_pid, p->p_comm,
- p->p_ucred ? p->p_ucred->cr_uid : -1,
+ td->td_ucred ? td->td_ucred->cr_uid : -1,
sig &~ WCOREFLAG,
sig & WCOREFLAG ? " (core dumped)" : "");
} else {
@@ -1970,7 +1956,7 @@ coredump(struct thread *td)
{
struct proc *p = td->td_proc;
register struct vnode *vp;
- register struct ucred *cred = p->p_ucred;
+ register struct ucred *cred = td->td_ucred;
struct flock lf;
struct nameidata nd;
struct vattr vattr;
@@ -2003,7 +1989,7 @@ coredump(struct thread *td)
PROC_UNLOCK(p);
restart:
- name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
+ name = expand_name(p->p_comm, td->td_ucred->cr_uid, p->p_pid);
if (name == NULL)
return (EINVAL);
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td); /* XXXKSE */
OpenPOWER on IntegriCloud