Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/sys_procdesc.c
Show First 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | procdesc_find(struct thread *td, int fd, cap_rights_t *rightsp, | ||||
error = fget(td, fd, rightsp, &fp); | error = fget(td, fd, rightsp, &fp); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
if (fp->f_type != DTYPE_PROCDESC) { | if (fp->f_type != DTYPE_PROCDESC) { | ||||
error = EBADF; | error = EBADF; | ||||
goto out; | goto out; | ||||
} | } | ||||
pd = fp->f_data; | pd = fp->f_data; | ||||
sx_slock(&proctree_lock); | sx_slock(&V_proctree_lock); | ||||
if (pd->pd_proc != NULL) { | if (pd->pd_proc != NULL) { | ||||
*p = pd->pd_proc; | *p = pd->pd_proc; | ||||
PROC_LOCK(*p); | PROC_LOCK(*p); | ||||
} else | } else | ||||
error = ESRCH; | error = ESRCH; | ||||
sx_sunlock(&proctree_lock); | sx_sunlock(&V_proctree_lock); | ||||
out: | out: | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Function to be used by procstat(1) sysctls when returning procdesc | * Function to be used by procstat(1) sysctls when returning procdesc | ||||
* information. | * information. | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | |||||
* We use the proctree_lock to ensure that process exit either happens | * We use the proctree_lock to ensure that process exit either happens | ||||
* strictly before or strictly after a concurrent call to procdesc_close(). | * strictly before or strictly after a concurrent call to procdesc_close(). | ||||
*/ | */ | ||||
int | int | ||||
procdesc_exit(struct proc *p) | procdesc_exit(struct proc *p) | ||||
{ | { | ||||
struct procdesc *pd; | struct procdesc *pd; | ||||
sx_assert(&proctree_lock, SA_XLOCKED); | sx_assert(&V_proctree_lock, SA_XLOCKED); | ||||
PROC_LOCK_ASSERT(p, MA_OWNED); | PROC_LOCK_ASSERT(p, MA_OWNED); | ||||
KASSERT(p->p_procdesc != NULL, ("procdesc_exit: p_procdesc NULL")); | KASSERT(p->p_procdesc != NULL, ("procdesc_exit: p_procdesc NULL")); | ||||
pd = p->p_procdesc; | pd = p->p_procdesc; | ||||
PROCDESC_LOCK(pd); | PROCDESC_LOCK(pd); | ||||
KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr == initproc, | KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr == V_initproc, | ||||
("procdesc_exit: closed && parent not init")); | ("procdesc_exit: closed && parent not init")); | ||||
pd->pd_flags |= PDF_EXITED; | pd->pd_flags |= PDF_EXITED; | ||||
pd->pd_xstat = KW_EXITCODE(p->p_xexit, p->p_xsig); | pd->pd_xstat = KW_EXITCODE(p->p_xexit, p->p_xsig); | ||||
/* | /* | ||||
* If the process descriptor has been closed, then we have nothing | * If the process descriptor has been closed, then we have nothing | ||||
* to do; return 1 so that init will get SIGCHLD and do the reaping. | * to do; return 1 so that init will get SIGCHLD and do the reaping. | ||||
Show All 20 Lines | |||||
* When a process descriptor is reaped, perhaps as a result of close() or | * When a process descriptor is reaped, perhaps as a result of close() or | ||||
* pdwait4(), release the process's reference on the process descriptor. | * pdwait4(), release the process's reference on the process descriptor. | ||||
*/ | */ | ||||
void | void | ||||
procdesc_reap(struct proc *p) | procdesc_reap(struct proc *p) | ||||
{ | { | ||||
struct procdesc *pd; | struct procdesc *pd; | ||||
sx_assert(&proctree_lock, SA_XLOCKED); | sx_assert(&V_proctree_lock, SA_XLOCKED); | ||||
KASSERT(p->p_procdesc != NULL, ("procdesc_reap: p_procdesc == NULL")); | KASSERT(p->p_procdesc != NULL, ("procdesc_reap: p_procdesc == NULL")); | ||||
pd = p->p_procdesc; | pd = p->p_procdesc; | ||||
pd->pd_proc = NULL; | pd->pd_proc = NULL; | ||||
p->p_procdesc = NULL; | p->p_procdesc = NULL; | ||||
procdesc_free(pd); | procdesc_free(pd); | ||||
} | } | ||||
Show All 9 Lines | procdesc_close(struct file *fp, struct thread *td) | ||||
struct proc *p; | struct proc *p; | ||||
KASSERT(fp->f_type == DTYPE_PROCDESC, ("procdesc_close: !procdesc")); | KASSERT(fp->f_type == DTYPE_PROCDESC, ("procdesc_close: !procdesc")); | ||||
pd = fp->f_data; | pd = fp->f_data; | ||||
fp->f_ops = &badfileops; | fp->f_ops = &badfileops; | ||||
fp->f_data = NULL; | fp->f_data = NULL; | ||||
sx_xlock(&proctree_lock); | sx_xlock(&V_proctree_lock); | ||||
PROCDESC_LOCK(pd); | PROCDESC_LOCK(pd); | ||||
pd->pd_flags |= PDF_CLOSED; | pd->pd_flags |= PDF_CLOSED; | ||||
PROCDESC_UNLOCK(pd); | PROCDESC_UNLOCK(pd); | ||||
p = pd->pd_proc; | p = pd->pd_proc; | ||||
if (p == NULL) { | if (p == NULL) { | ||||
/* | /* | ||||
* This is the case where process' exit status was already | * This is the case where process' exit status was already | ||||
* collected and procdesc_reap() was already called. | * collected and procdesc_reap() was already called. | ||||
*/ | */ | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&V_proctree_lock); | ||||
} else { | } else { | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
AUDIT_ARG_PROCESS(p); | AUDIT_ARG_PROCESS(p); | ||||
if (p->p_state == PRS_ZOMBIE) { | if (p->p_state == PRS_ZOMBIE) { | ||||
/* | /* | ||||
* If the process is already dead and just awaiting | * If the process is already dead and just awaiting | ||||
* reaping, do that now. This will release the | * reaping, do that now. This will release the | ||||
* process's reference to the process descriptor when it | * process's reference to the process descriptor when it | ||||
Show All 13 Lines | if (p->p_state == PRS_ZOMBIE) { | ||||
procdesc_free(pd); | procdesc_free(pd); | ||||
/* | /* | ||||
* Next, reparent it to init(8) so that there's someone | * Next, reparent it to init(8) so that there's someone | ||||
* to pick up the pieces; finally, terminate with | * to pick up the pieces; finally, terminate with | ||||
* prejudice. | * prejudice. | ||||
*/ | */ | ||||
p->p_sigparent = SIGCHLD; | p->p_sigparent = SIGCHLD; | ||||
proc_reparent(p, initproc); | proc_reparent(p, V_initproc); | ||||
if ((pd->pd_flags & PDF_DAEMON) == 0) | if ((pd->pd_flags & PDF_DAEMON) == 0) | ||||
kern_psignal(p, SIGKILL); | kern_psignal(p, SIGKILL); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
sx_xunlock(&proctree_lock); | sx_xunlock(&V_proctree_lock); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Release the file descriptor's reference on the process descriptor. | * Release the file descriptor's reference on the process descriptor. | ||||
*/ | */ | ||||
procdesc_free(pd); | procdesc_free(pd); | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | procdesc_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, | ||||
/* | /* | ||||
* XXXRW: Perhaps we should cache some more information from the | * XXXRW: Perhaps we should cache some more information from the | ||||
* process so that we can return it reliably here even after it has | * process so that we can return it reliably here even after it has | ||||
* died. For example, caching its credential data. | * died. For example, caching its credential data. | ||||
*/ | */ | ||||
bzero(sb, sizeof(*sb)); | bzero(sb, sizeof(*sb)); | ||||
pd = fp->f_data; | pd = fp->f_data; | ||||
sx_slock(&proctree_lock); | sx_slock(&V_proctree_lock); | ||||
if (pd->pd_proc != NULL) { | if (pd->pd_proc != NULL) { | ||||
PROC_LOCK(pd->pd_proc); | PROC_LOCK(pd->pd_proc); | ||||
AUDIT_ARG_PROCESS(pd->pd_proc); | AUDIT_ARG_PROCESS(pd->pd_proc); | ||||
/* Set birth and [acm] times to process start time. */ | /* Set birth and [acm] times to process start time. */ | ||||
pstart = pd->pd_proc->p_stats->p_start; | pstart = pd->pd_proc->p_stats->p_start; | ||||
getboottime(&boottime); | getboottime(&boottime); | ||||
timevaladd(&pstart, &boottime); | timevaladd(&pstart, &boottime); | ||||
TIMEVAL_TO_TIMESPEC(&pstart, &sb->st_birthtim); | TIMEVAL_TO_TIMESPEC(&pstart, &sb->st_birthtim); | ||||
sb->st_atim = sb->st_birthtim; | sb->st_atim = sb->st_birthtim; | ||||
sb->st_ctim = sb->st_birthtim; | sb->st_ctim = sb->st_birthtim; | ||||
sb->st_mtim = sb->st_birthtim; | sb->st_mtim = sb->st_birthtim; | ||||
if (pd->pd_proc->p_state != PRS_ZOMBIE) | if (pd->pd_proc->p_state != PRS_ZOMBIE) | ||||
sb->st_mode = S_IFREG | S_IRWXU; | sb->st_mode = S_IFREG | S_IRWXU; | ||||
else | else | ||||
sb->st_mode = S_IFREG; | sb->st_mode = S_IFREG; | ||||
sb->st_uid = pd->pd_proc->p_ucred->cr_ruid; | sb->st_uid = pd->pd_proc->p_ucred->cr_ruid; | ||||
sb->st_gid = pd->pd_proc->p_ucred->cr_rgid; | sb->st_gid = pd->pd_proc->p_ucred->cr_rgid; | ||||
PROC_UNLOCK(pd->pd_proc); | PROC_UNLOCK(pd->pd_proc); | ||||
} else | } else | ||||
sb->st_mode = S_IFREG; | sb->st_mode = S_IFREG; | ||||
sx_sunlock(&proctree_lock); | sx_sunlock(&V_proctree_lock); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
procdesc_fill_kinfo(struct file *fp, struct kinfo_file *kif, | procdesc_fill_kinfo(struct file *fp, struct kinfo_file *kif, | ||||
struct filedesc *fdp) | struct filedesc *fdp) | ||||
{ | { | ||||
struct procdesc *pdp; | struct procdesc *pdp; | ||||
kif->kf_type = KF_TYPE_PROCDESC; | kif->kf_type = KF_TYPE_PROCDESC; | ||||
pdp = fp->f_data; | pdp = fp->f_data; | ||||
kif->kf_un.kf_proc.kf_pid = pdp->pd_pid; | kif->kf_un.kf_proc.kf_pid = pdp->pd_pid; | ||||
return (0); | return (0); | ||||
} | } |