PR kern/37917 /bin/ps no longer shows zombies

This commit is contained in:
ad 2008-04-29 16:21:27 +00:00
parent a4c98bcccd
commit b872c0e53d
3 changed files with 113 additions and 115 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: core_netbsd.c,v 1.14 2006/11/01 10:17:58 yamt Exp $ */
/* $NetBSD: core_netbsd.c,v 1.15 2008/04/29 16:21:27 ad Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@ -50,7 +50,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.14 2006/11/01 10:17:58 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.15 2008/04/29 16:21:27 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -105,7 +105,7 @@ CORENAME(coredump_netbsd)(struct lwp *l, void *iocookie)
* the user area. For now, it's dead.
*/
memcpy(&p->p_addr->u_kproc.kp_proc, p, sizeof(struct proc));
fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
fill_eproc(p, &p->p_addr->u_kproc.kp_eproc, false);
#endif
error = CORENAME(cpu_coredump)(l, NULL, &cs.core);
if (error)

View File

@ -1,4 +1,4 @@
/* $NetBSD: init_sysctl.c,v 1.134 2008/04/28 20:24:02 martin Exp $ */
/* $NetBSD: init_sysctl.c,v 1.135 2008/04/29 16:21:27 ad Exp $ */
/*-
* Copyright (c) 2003, 2007, 2008 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.134 2008/04/28 20:24:02 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.135 2008/04/29 16:21:27 ad Exp $");
#include "opt_sysv.h"
#include "opt_posix.h"
@ -183,7 +183,7 @@ static int sysctl_hw_usermem(SYSCTLFN_PROTO);
static int sysctl_hw_cnmagic(SYSCTLFN_PROTO);
static u_int sysctl_map_flags(const u_int *, u_int);
static void fill_kproc2(struct proc *, struct kinfo_proc2 *);
static void fill_kproc2(struct proc *, struct kinfo_proc2 *, bool);
static void fill_lwp(struct lwp *l, struct kinfo_lwp *kl);
static void fill_file(struct kinfo_file *, const file_t *, const fdfile_t *,
int, pid_t);
@ -2133,13 +2133,12 @@ sysctl_doeproc(SYSCTLFN_ARGS)
struct eproc *eproc;
struct kinfo_proc2 *kproc2;
struct kinfo_proc *dp;
struct proc *p;
struct proc *p, *next, *marker;
char *where, *dp2;
int type, op, arg;
int type, op, arg, error;
u_int elem_size, elem_count;
size_t buflen, needed;
bool match;
int error;
bool match, zombie, mmmbrains;
if (namelen == 1 && name[0] == CTL_QUERY)
return (sysctl_query(SYSCTLFN_CALL(rnode)));
@ -2178,9 +2177,21 @@ sysctl_doeproc(SYSCTLFN_ARGS)
eproc = NULL;
kproc2 = kmem_alloc(sizeof(*kproc2), KM_SLEEP);
}
marker = kmem_alloc(sizeof(*marker), KM_SLEEP);
mutex_enter(proc_lock);
LIST_FOREACH(p, &allproc, p_list) {
mmmbrains = true;
for (p = LIST_FIRST(&allproc);; p = next) {
if (p == NULL) {
if (mmmbrains) {
p = LIST_FIRST(&zombproc);
mmmbrains = false;
}
if (p == NULL)
break;
}
next = LIST_NEXT(p, p_list);
/*
* Skip embryonic processes.
*/
@ -2267,28 +2278,26 @@ sysctl_doeproc(SYSCTLFN_ARGS)
/*
* Grab a hold on the process.
*/
if (!rw_tryenter(&p->p_reflock, RW_READER)) {
mutex_exit(p->p_lock);
continue;
zombie = !rw_tryenter(&p->p_reflock, RW_READER);
if (zombie) {
LIST_INSERT_AFTER(p, marker, p_list);
}
if (type == KERN_PROC) {
if (buflen >= sizeof(struct kinfo_proc)) {
fill_eproc(p, eproc);
fill_eproc(p, eproc, zombie);
mutex_exit(p->p_lock);
mutex_exit(proc_lock);
error = dcopyout(l, p, &dp->kp_proc,
sizeof(struct proc));
mutex_enter(proc_lock);
if (error) {
rw_exit(&p->p_reflock);
goto cleanup;
goto bah;
}
error = dcopyout(l, eproc, &dp->kp_eproc,
sizeof(*eproc));
if (error) {
rw_exit(&p->p_reflock);
goto cleanup;
goto bah;
}
dp++;
buflen -= sizeof(struct kinfo_proc);
@ -2298,7 +2307,7 @@ sysctl_doeproc(SYSCTLFN_ARGS)
needed += sizeof(struct kinfo_proc);
} else { /* KERN_PROC2 */
if (buflen >= elem_size && elem_count > 0) {
fill_kproc2(p, kproc2);
fill_kproc2(p, kproc2, zombie);
mutex_exit(p->p_lock);
mutex_exit(proc_lock);
/*
@ -2309,8 +2318,7 @@ sysctl_doeproc(SYSCTLFN_ARGS)
min(sizeof(*kproc2), elem_size));
mutex_enter(proc_lock);
if (error) {
rw_exit(&p->p_reflock);
goto cleanup;
goto bah;
}
dp2 += elem_size;
buflen -= elem_size;
@ -2324,7 +2332,11 @@ sysctl_doeproc(SYSCTLFN_ARGS)
/*
* Release reference to process.
*/
rw_exit(&p->p_reflock);
if (zombie) {
LIST_REMOVE(marker, p_list);
} else {
rw_exit(&p->p_reflock);
}
}
mutex_exit(proc_lock);
@ -2345,8 +2357,15 @@ sysctl_doeproc(SYSCTLFN_ARGS)
kmem_free(kproc2, sizeof(*kproc2));
if (eproc)
kmem_free(eproc, sizeof(*eproc));
if (marker)
kmem_free(marker, sizeof(*marker));
sysctl_relock();
return 0;
bah:
if (zombie)
LIST_REMOVE(marker, p_list);
else
rw_exit(&p->p_reflock);
cleanup:
mutex_exit(proc_lock);
out:
@ -2354,6 +2373,8 @@ sysctl_doeproc(SYSCTLFN_ARGS)
kmem_free(kproc2, sizeof(*kproc2));
if (eproc)
kmem_free(eproc, sizeof(*eproc));
if (marker)
kmem_free(marker, sizeof(*marker));
sysctl_relock();
return error;
}
@ -2839,17 +2860,21 @@ sysctl_consdev(SYSCTLFN_ARGS)
* Fill in a kinfo_proc2 structure for the specified process.
*/
static void
fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
fill_kproc2(struct proc *p, struct kinfo_proc2 *ki, bool zombie)
{
struct tty *tp;
struct lwp *l, *l2;
struct timeval ut, st, rt;
sigset_t ss1, ss2;
struct rusage ru;
struct vmspace *vm;
int tmp;
KASSERT(mutex_owned(proc_lock));
KASSERT(mutex_owned(p->p_lock));
sigemptyset(&ss1);
sigemptyset(&ss2);
memset(ki, 0, sizeof(*ki));
ki->p_paddr = PTRTOUINT64(p);
@ -2862,51 +2887,33 @@ fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
ki->p_sess = PTRTOUINT64(p->p_session);
ki->p_tsess = 0; /* may be changed if controlling tty below */
ki->p_ru = PTRTOUINT64(&p->p_stats->p_ru);
ki->p_eflag = 0;
ki->p_exitsig = p->p_exitsig;
ki->p_flag = sysctl_map_flags(sysctl_flagmap, p->p_flag);
ki->p_flag |= sysctl_map_flags(sysctl_sflagmap, p->p_sflag);
ki->p_flag |= sysctl_map_flags(sysctl_slflagmap, p->p_slflag);
ki->p_flag |= sysctl_map_flags(sysctl_lflagmap, p->p_lflag);
ki->p_flag |= sysctl_map_flags(sysctl_stflagmap, p->p_stflag);
ki->p_pid = p->p_pid;
if (p->p_pptr)
ki->p_ppid = p->p_pptr->p_pid;
else
ki->p_ppid = 0;
ki->p_sid = p->p_session->s_sid;
ki->p__pgid = p->p_pgrp->pg_id;
ki->p_tpgid = NO_PGID; /* may be changed if controlling tty below */
ki->p_uid = kauth_cred_geteuid(p->p_cred);
ki->p_ruid = kauth_cred_getuid(p->p_cred);
ki->p_gid = kauth_cred_getegid(p->p_cred);
ki->p_rgid = kauth_cred_getgid(p->p_cred);
ki->p_svuid = kauth_cred_getsvuid(p->p_cred);
ki->p_svgid = kauth_cred_getsvgid(p->p_cred);
ki->p_ngroups = kauth_cred_ngroups(p->p_cred);
kauth_cred_getgroups(p->p_cred, ki->p_groups,
min(ki->p_ngroups, sizeof(ki->p_groups) / sizeof(ki->p_groups[0])),
UIO_SYSSPACE);
ki->p_jobc = p->p_pgrp->pg_jobc;
if ((p->p_lflag & PL_CONTROLT) && (tp = p->p_session->s_ttyp)) {
ki->p_tdev = tp->t_dev;
ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
ki->p_tsess = PTRTOUINT64(tp->t_session);
} else {
ki->p_tdev = NODEV;
}
ki->p_uticks = p->p_uticks;
ki->p_sticks = p->p_sticks;
ki->p_iticks = p->p_iticks;
ki->p_tpgid = NO_PGID; /* may be changed if controlling tty below */
ki->p_tracep = PTRTOUINT64(p->p_tracep);
ki->p_traceflag = p->p_traceflag;
@ -2916,45 +2923,20 @@ fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
ki->p_cpticks = 0;
ki->p_pctcpu = p->p_pctcpu;
ki->p_estcpu = 0;
ss1 = p->p_sigpend.sp_set;
LIST_FOREACH(l, &p->p_lwps, l_sibling) {
/* This is hardly correct, but... */
sigplusset(&l->l_sigpend.sp_set, &ss1);
sigplusset(&l->l_sigmask, &ss2);
ki->p_cpticks += l->l_cpticks;
ki->p_pctcpu += l->l_pctcpu;
ki->p_estcpu += l->l_estcpu;
}
memcpy(&ki->p_siglist, &ss1, sizeof(ki_sigset_t));
memcpy(&ki->p_sigmask, &ss2, sizeof(ki_sigset_t));
ki->p_stat = p->p_stat; /* Will likely be overridden by LWP status */
ki->p_realstat = p->p_stat;
ki->p_nice = p->p_nice;
ki->p_xstat = p->p_xstat;
ki->p_acflag = p->p_acflag;
strncpy(ki->p_comm, p->p_comm,
min(sizeof(ki->p_comm), sizeof(p->p_comm)));
strncpy(ki->p_login, p->p_session->s_login,
min(sizeof ki->p_login - 1, sizeof p->p_session->s_login));
ki->p_nlwps = p->p_nlwps;
ki->p_realflag = ki->p_flag;
if (p->p_stat == SIDL || P_ZOMBIE(p)) {
ki->p_vm_rssize = 0;
ki->p_vm_tsize = 0;
ki->p_vm_dsize = 0;
ki->p_vm_ssize = 0;
ki->p_nrlwps = 0;
l = NULL;
} else {
struct vmspace *vm = p->p_vmspace;
int tmp;
if (p->p_stat != SIDL && !P_ZOMBIE(p) && !zombie) {
vm = p->p_vmspace;
ki->p_vm_rssize = vm_resident_count(vm);
ki->p_vm_tsize = vm->vm_tsize;
ki->p_vm_dsize = vm->vm_dsize;
@ -2981,21 +2963,42 @@ fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
if (l->l_wchan)
strncpy(ki->p_wmesg, l->l_wmesg, sizeof(ki->p_wmesg));
ki->p_wchan = PTRTOUINT64(l->l_wchan);
ki->p_cpuid = l->l_cpu->ci_cpuid;
lwp_unlock(l);
LIST_FOREACH(l, &p->p_lwps, l_sibling) {
/* This is hardly correct, but... */
sigplusset(&l->l_sigpend.sp_set, &ss1);
sigplusset(&l->l_sigmask, &ss2);
ki->p_cpticks += l->l_cpticks;
ki->p_pctcpu += l->l_pctcpu;
ki->p_estcpu += l->l_estcpu;
}
}
if (p->p_session->s_ttyvp)
ki->p_eflag |= EPROC_CTTY;
if (SESS_LEADER(p))
ki->p_eflag |= EPROC_SLEADER;
sigplusset(&p->p_sigpend.sp_set, &ss2);
memcpy(&ki->p_siglist, &ss1, sizeof(ki_sigset_t));
memcpy(&ki->p_sigmask, &ss2, sizeof(ki_sigset_t));
/* XXX Is this double check necessary? */
if (P_ZOMBIE(p)) {
ki->p_uvalid = 0;
ki->p_rtime_sec = 0;
ki->p_rtime_usec = 0;
} else {
if (p->p_session != NULL) {
ki->p_sid = p->p_session->s_sid;
ki->p__pgid = p->p_pgrp->pg_id;
if (p->p_session->s_ttyvp)
ki->p_eflag |= EPROC_CTTY;
if (SESS_LEADER(p))
ki->p_eflag |= EPROC_SLEADER;
strncpy(ki->p_login, p->p_session->s_login,
min(sizeof ki->p_login - 1, sizeof p->p_session->s_login));
ki->p_jobc = p->p_pgrp->pg_jobc;
if ((p->p_lflag & PL_CONTROLT) && (tp = p->p_session->s_ttyp)) {
ki->p_tdev = tp->t_dev;
ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
ki->p_tsess = PTRTOUINT64(tp->t_session);
} else {
ki->p_tdev = NODEV;
}
}
if (!P_ZOMBIE(p) && !zombie) {
ki->p_uvalid = 1;
ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
@ -3011,8 +3014,8 @@ fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
ki->p_uru_nvcsw = 0;
ki->p_uru_nivcsw = 0;
LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
ki->p_uru_nvcsw += (l->l_ncsw - l->l_nivcsw);
ki->p_uru_nivcsw += l->l_nivcsw;
ki->p_uru_nvcsw += (l2->l_ncsw - l2->l_nivcsw);
ki->p_uru_nivcsw += l2->l_nivcsw;
ruadd(&ru, &l2->l_ru);
}
ki->p_uru_maxrss = ru.ru_maxrss;
@ -3033,8 +3036,6 @@ fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
ki->p_uctime_sec = ut.tv_sec;
ki->p_uctime_usec = ut.tv_usec;
}
if (l != NULL)
ki->p_cpuid = l->l_cpu->ci_cpuid;
}
/*
@ -3085,7 +3086,7 @@ fill_lwp(struct lwp *l, struct kinfo_lwp *kl)
* Fill in an eproc structure for the specified process.
*/
void
fill_eproc(struct proc *p, struct eproc *ep)
fill_eproc(struct proc *p, struct eproc *ep, bool zombie)
{
struct tty *tp;
struct lwp *l;
@ -3093,17 +3094,15 @@ fill_eproc(struct proc *p, struct eproc *ep)
KASSERT(mutex_owned(proc_lock));
KASSERT(mutex_owned(p->p_lock));
memset(ep, 0, sizeof(*ep));
ep->e_paddr = p;
ep->e_sess = p->p_session;
kauth_cred_topcred(p->p_cred, &ep->e_pcred);
kauth_cred_toucred(p->p_cred, &ep->e_ucred);
if (p->p_stat == SIDL || P_ZOMBIE(p)) {
ep->e_vm.vm_rssize = 0;
ep->e_vm.vm_tsize = 0;
ep->e_vm.vm_dsize = 0;
ep->e_vm.vm_ssize = 0;
/* ep->e_vm.vm_pmap = XXX; */
} else {
if (p->p_cred) {
kauth_cred_topcred(p->p_cred, &ep->e_pcred);
kauth_cred_toucred(p->p_cred, &ep->e_ucred);
}
if (p->p_stat != SIDL && !P_ZOMBIE(p) && !zombie) {
struct vmspace *vm = p->p_vmspace;
ep->e_vm.vm_rssize = vm_resident_count(vm);
@ -3120,25 +3119,24 @@ fill_eproc(struct proc *p, struct eproc *ep)
}
if (p->p_pptr)
ep->e_ppid = p->p_pptr->p_pid;
else
ep->e_ppid = 0;
ep->e_pgid = p->p_pgrp->pg_id;
ep->e_sid = ep->e_sess->s_sid;
ep->e_jobc = p->p_pgrp->pg_jobc;
if ((p->p_lflag & PL_CONTROLT) &&
(tp = ep->e_sess->s_ttyp)) {
ep->e_tdev = tp->t_dev;
ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
ep->e_tsess = tp->t_session;
} else
ep->e_tdev = NODEV;
if (p->p_pgrp && p->p_session) {
ep->e_pgid = p->p_pgrp->pg_id;
ep->e_jobc = p->p_pgrp->pg_jobc;
ep->e_sid = p->p_session->s_sid;
if ((p->p_lflag & PL_CONTROLT) &&
(tp = ep->e_sess->s_ttyp)) {
ep->e_tdev = tp->t_dev;
ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
ep->e_tsess = tp->t_session;
} else
ep->e_tdev = NODEV;
ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
if (SESS_LEADER(p))
ep->e_flag |= EPROC_SLEADER;
strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
}
ep->e_xsize = ep->e_xrssize = 0;
ep->e_xccount = ep->e_xswrss = 0;
ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
if (SESS_LEADER(p))
ep->e_flag |= EPROC_SLEADER;
strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
}
u_int

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysctl.h,v 1.175 2008/02/29 06:37:57 matt Exp $ */
/* $NetBSD: sysctl.h,v 1.176 2008/04/29 16:21:27 ad Exp $ */
/*
* Copyright (c) 1989, 1993
@ -1115,7 +1115,7 @@ typedef int (*sysctlfn)(SYSCTLFN_PROTO);
/*
* used in more than just sysctl
*/
void fill_eproc(struct proc *, struct eproc *);
void fill_eproc(struct proc *, struct eproc *, bool);
/*
* subsystem setup