The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4d707825bf62ee73a32b615846eff9c4a9bda538

commit 4d707825bf62ee73a32b615846eff9c4a9bda538
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-01-08 03:37:42 +0000
Commit:     Konstantin Belousov <[email protected]>
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,

Reply via email to