Add pdwait(2)
Reviewed by: asomers, markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54592
This commit is contained in:
@@ -281,6 +281,37 @@ freebsd32_wait6(struct thread *td, struct freebsd32_wait6_args *uap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_pdwait(struct thread *td, struct freebsd32_pdwait_args *uap)
|
||||
{
|
||||
struct __wrusage32 wru32;
|
||||
struct __wrusage wru, *wrup;
|
||||
struct __siginfo32 si32;
|
||||
struct __siginfo si, *sip;
|
||||
int error, status;
|
||||
|
||||
wrup = uap->wrusage != NULL ? &wru : NULL;
|
||||
if (uap->info != NULL) {
|
||||
sip = &si;
|
||||
bzero(sip, sizeof(*sip));
|
||||
} else {
|
||||
sip = NULL;
|
||||
}
|
||||
error = kern_pdwait(td, uap->fd, &status, uap->options, wrup, sip);
|
||||
if (uap->status != NULL && error == 0)
|
||||
error = copyout(&status, uap->status, sizeof(status));
|
||||
if (uap->wrusage != NULL && error == 0) {
|
||||
freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);
|
||||
freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);
|
||||
error = copyout(&wru32, uap->wrusage, sizeof(wru32));
|
||||
}
|
||||
if (uap->info != NULL && error == 0) {
|
||||
siginfo_to_siginfo32 (&si, &si32);
|
||||
error = copyout(&si32, uap->info, sizeof(si32));
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_FREEBSD4
|
||||
static void
|
||||
copy_statfs(struct statfs *in, struct ostatfs32 *out)
|
||||
|
||||
@@ -906,6 +906,33 @@ sys_wait6(struct thread *td, struct wait6_args *uap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
sys_pdwait(struct thread *td, struct pdwait_args *uap)
|
||||
{
|
||||
struct __wrusage wru, *wrup;
|
||||
siginfo_t si, *sip;
|
||||
int error, status;
|
||||
|
||||
wrup = uap->wrusage != NULL ? &wru : NULL;
|
||||
|
||||
if (uap->info != NULL) {
|
||||
sip = &si;
|
||||
bzero(sip, sizeof(*sip));
|
||||
} else {
|
||||
sip = NULL;
|
||||
}
|
||||
|
||||
error = kern_pdwait(td, uap->fd, &status, uap->options, wrup, sip);
|
||||
|
||||
if (uap->status != NULL && error == 0)
|
||||
error = copyout(&status, uap->status, sizeof(status));
|
||||
if (uap->wrusage != NULL && error == 0)
|
||||
error = copyout(&wru, uap->wrusage, sizeof(wru));
|
||||
if (uap->info != NULL && error == 0)
|
||||
error = copyout(&si, uap->info, sizeof(si));
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reap the remains of a zombie process and optionally return status and
|
||||
* rusage. Asserts and will release both the proctree_lock and the process
|
||||
@@ -1476,6 +1503,84 @@ kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
kern_pdwait(struct thread *td, int fd, int *status,
|
||||
int options, struct __wrusage *wrusage, siginfo_t *siginfo)
|
||||
{
|
||||
struct proc *p;
|
||||
struct file *fp;
|
||||
struct procdesc *pd;
|
||||
int error;
|
||||
|
||||
AUDIT_ARG_FD(fd);
|
||||
AUDIT_ARG_VALUE(options);
|
||||
|
||||
error = wait6_checkopt(options);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = fget(td, fd, &cap_pdwait_rights, &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (fp->f_type != DTYPE_PROCDESC) {
|
||||
error = EINVAL;
|
||||
goto exit_unlocked;
|
||||
}
|
||||
pd = fp->f_data;
|
||||
|
||||
for (;;) {
|
||||
/* We own a reference on the procdesc file. */
|
||||
KASSERT((pd->pd_flags & PDF_CLOSED) == 0,
|
||||
("PDF_CLOSED proc %p procdesc %p pd flags %#x",
|
||||
p, pd, pd->pd_flags));
|
||||
|
||||
sx_xlock(&proctree_lock);
|
||||
p = pd->pd_proc;
|
||||
if (p == NULL) {
|
||||
error = ESRCH;
|
||||
goto exit_tree_locked;
|
||||
}
|
||||
PROC_LOCK(p);
|
||||
|
||||
error = p_canwait(td, p);
|
||||
if (error != 0)
|
||||
break;
|
||||
if ((options & WEXITED) == 0 && p->p_state == PRS_ZOMBIE) {
|
||||
error = ESRCH;
|
||||
break;
|
||||
}
|
||||
|
||||
wait_fill_siginfo(p, siginfo);
|
||||
wait_fill_wrusage(p, wrusage);
|
||||
|
||||
if (p->p_state == PRS_ZOMBIE) {
|
||||
proc_reap(td, p, status, options);
|
||||
goto exit_unlocked;
|
||||
}
|
||||
|
||||
if (wait6_check_alive(td, options, p, status, siginfo))
|
||||
goto exit_unlocked;
|
||||
|
||||
if ((options & WNOHANG) != 0) {
|
||||
error = EWOULDBLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
PROC_UNLOCK(p);
|
||||
error = sx_sleep(&p->p_procdesc, &proctree_lock,
|
||||
PWAIT | PCATCH | PDROP, "pdwait", 0);
|
||||
if (error != 0)
|
||||
goto exit_unlocked;
|
||||
}
|
||||
|
||||
PROC_UNLOCK(p);
|
||||
exit_tree_locked:
|
||||
sx_xunlock(&proctree_lock);
|
||||
exit_unlocked:
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
proc_add_orphan(struct proc *child, struct proc *parent)
|
||||
{
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
#include <sys/procdesc.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
@@ -321,6 +322,9 @@ procdesc_exit(struct proc *p)
|
||||
}
|
||||
KNOTE_LOCKED(&pd->pd_selinfo.si_note, NOTE_EXIT);
|
||||
PROCDESC_UNLOCK(pd);
|
||||
|
||||
/* Wakeup all waiters for this procdesc' process exit. */
|
||||
wakeup(&p->p_procdesc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -3411,4 +3411,14 @@
|
||||
);
|
||||
}
|
||||
|
||||
601 AUE_PDWAIT STD|CAPENABLED {
|
||||
int pdwait(
|
||||
int fd,
|
||||
_Out_opt_ int *status,
|
||||
int options,
|
||||
_Out_opt_ _Contains_long_ struct __wrusage *wrusage,
|
||||
_Out_opt_ _Contains_long_ptr_ struct __siginfo *info
|
||||
);
|
||||
}
|
||||
|
||||
; vim: syntax=off
|
||||
|
||||
@@ -286,6 +286,8 @@ int kern_posix_fallocate(struct thread *td, int fd, off_t offset,
|
||||
off_t len);
|
||||
int kern_fspacectl(struct thread *td, int fd, int cmd,
|
||||
const struct spacectl_range *, int flags, struct spacectl_range *);
|
||||
int kern_pdwait(struct thread *td, int fd, int *status,
|
||||
int options, struct __wrusage *wrusage, siginfo_t *sip);
|
||||
int kern_procctl(struct thread *td, enum idtype idtype, id_t id, int com,
|
||||
void *data);
|
||||
int kern_pread(struct thread *td, int fd, void *buf, size_t nbyte,
|
||||
|
||||
Reference in New Issue
Block a user