diff options
author | kib <kib@FreeBSD.org> | 2012-11-16 08:25:06 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-11-16 08:25:06 +0000 |
commit | 801de097168c553834c3d068ebd8c7a2b03d00a9 (patch) | |
tree | ccb07158db9f2172e2f9d621713636008488e9e4 /sys/kern/kern_proc.c | |
parent | 94ab185bfb54474f2717c567bd0643288c5c9492 (diff) | |
download | FreeBSD-src-801de097168c553834c3d068ebd8c7a2b03d00a9.zip FreeBSD-src-801de097168c553834c3d068ebd8c7a2b03d00a9.tar.gz |
In pget(9), if PGET_NOTWEXIT flag is not specified, also search the
zombie list for the pid. This allows several kern.proc sysctls to
report useful information for zombies.
Hold the allproc_lock around all searches instead of relocking it.
Remove private pfind_locked() from the new nfs client code.
Requested and reviewed by: pjd
Tested by: pho
MFC after: 3 weeks
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index d6db62f..0ab5568 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -137,6 +137,7 @@ static void proc_dtor(void *mem, int size, void *arg); static int proc_init(void *mem, int size, int flags); static void proc_fini(void *mem, int size); static void pargs_free(struct pargs *pa); +static struct proc *zpfind_locked(pid_t pid); /* * Other process lists @@ -284,20 +285,13 @@ inferior(p) return (1); } -/* - * Locate a process by number; return only "live" processes -- i.e., neither - * zombies nor newly born but incompletely initialized processes. By not - * returning processes in the PRS_NEW state, we allow callers to avoid - * testing for that condition to avoid dereferencing p_ucred, et al. - */ struct proc * -pfind(pid) - register pid_t pid; +pfind_locked(pid_t pid) { - register struct proc *p; + struct proc *p; - sx_slock(&allproc_lock); - LIST_FOREACH(p, PIDHASH(pid), p_hash) + sx_assert(&allproc_lock, SX_LOCKED); + LIST_FOREACH(p, PIDHASH(pid), p_hash) { if (p->p_pid == pid) { PROC_LOCK(p); if (p->p_state == PRS_NEW) { @@ -306,17 +300,34 @@ pfind(pid) } break; } + } + return (p); +} + +/* + * Locate a process by number; return only "live" processes -- i.e., neither + * zombies nor newly born but incompletely initialized processes. By not + * returning processes in the PRS_NEW state, we allow callers to avoid + * testing for that condition to avoid dereferencing p_ucred, et al. + */ +struct proc * +pfind(pid_t pid) +{ + struct proc *p; + + sx_slock(&allproc_lock); + p = pfind_locked(pid); sx_sunlock(&allproc_lock); return (p); } static struct proc * -pfind_tid(pid_t tid) +pfind_tid_locked(pid_t tid) { struct proc *p; struct thread *td; - sx_slock(&allproc_lock); + sx_assert(&allproc_lock, SX_LOCKED); FOREACH_PROC_IN_SYSTEM(p) { PROC_LOCK(p); if (p->p_state == PRS_NEW) { @@ -330,7 +341,6 @@ pfind_tid(pid_t tid) PROC_UNLOCK(p); } found: - sx_sunlock(&allproc_lock); return (p); } @@ -364,12 +374,16 @@ pget(pid_t pid, int flags, struct proc **pp) struct proc *p; int error; + sx_slock(&allproc_lock); if (pid <= PID_MAX) - p = pfind(pid); + p = pfind_locked(pid); else if ((flags & PGET_NOTID) == 0) - p = pfind_tid(pid); + p = pfind_tid_locked(pid); else p = NULL; + if (p == NULL && (flags & PGET_NOTWEXIT) == 0) + p = zpfind_locked(pid); + sx_sunlock(&allproc_lock); if (p == NULL) return (ESRCH); if ((flags & PGET_CANSEE) != 0) { @@ -1044,6 +1058,21 @@ pstats_free(struct pstats *ps) free(ps, M_SUBPROC); } +static struct proc * +zpfind_locked(pid_t pid) +{ + struct proc *p; + + sx_assert(&allproc_lock, SX_LOCKED); + LIST_FOREACH(p, &zombproc, p_list) { + if (p->p_pid == pid) { + PROC_LOCK(p); + break; + } + } + return (p); +} + /* * Locate a zombie process by number */ @@ -1053,11 +1082,7 @@ zpfind(pid_t pid) struct proc *p; sx_slock(&allproc_lock); - LIST_FOREACH(p, &zombproc, p_list) - if (p->p_pid == pid) { - PROC_LOCK(p); - break; - } + p = zpfind_locked(pid); sx_sunlock(&allproc_lock); return (p); } |