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:
Konstantin Belousov
2026-01-08 05:37:42 +02:00
parent 09984871d8
commit 4d707825bf
5 changed files with 152 additions and 0 deletions
+31
View File
@@ -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)
+105
View File
@@ -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)
{
+4
View File
@@ -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);
}
+10
View File
@@ -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
+2
View File
@@ -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,