git: 4d707825bf62 - main - Add pdwait(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 25 Jan 2026 15:56:58 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=4d707825bf62ee73a32b615846eff9c4a9bda538
commit 4d707825bf62ee73a32b615846eff9c4a9bda538
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-08 03:37:42 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-01-25 15:54:02 +0000
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
---
sys/compat/freebsd32/freebsd32_misc.c | 31 ++++++++++
sys/kern/kern_exit.c | 105 ++++++++++++++++++++++++++++++++++
sys/kern/sys_procdesc.c | 4 ++
sys/kern/syscalls.master | 10 ++++
sys/sys/syscallsubr.h | 2 +
5 files changed, 152 insertions(+)
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 8a2c179926d8..c76c9d5c1838 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -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)
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index beb29e890bd7..18ea3a7bd29d 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -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 @@ loop_locked:
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)
{
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 4f5b08003735..ec3b37f96148 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -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);
}
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 1d0608297913..8a30e5931a0e 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -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
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index 4ddd2eba25c8..e2bbbc188553 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -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,