The branch stable/15 has been updated by des:

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

commit 4ce8f2940a6a62b4d79b54d9d9a0c1acaca0ad5c
Author:     Dag-Erling Smørgrav <[email protected]>
AuthorDate: 2026-07-27 10:15:26 +0000
Commit:     Dag-Erling Smørgrav <[email protected]>
CommitDate: 2026-08-03 11:32:12 +0000

    kqueue: Add NOTE_REAP
    
    Add a NOTE_REAP event for EVFILTER_PROC which provides a notification
    when the process is reaped.
    
    MFC after:      1 week
    Sponsored by:   Klara, Inc.
    Sponsored by:   NetApp, Inc.
    Reviewed by:    kib, markj
    Differential Revision:  https://reviews.freebsd.org/D58313
    
    (cherry picked from commit 2bacbbecb165dd761ea7ec2fc35630db61508cdf)
---
 lib/libsys/kqueue.2      | 10 ++++++++--
 lib/libsysdecode/flags.c |  4 ++--
 sys/kern/kern_event.c    | 13 ++++++++-----
 sys/kern/kern_exit.c     |  1 +
 sys/kern/sys_procdesc.c  |  9 ++++++---
 sys/sys/event.h          | 11 ++++-------
 6 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/lib/libsys/kqueue.2 b/lib/libsys/kqueue.2
index 6e2d2df40ead..b596a705e08f 100644
--- a/lib/libsys/kqueue.2
+++ b/lib/libsys/kqueue.2
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd January 24, 2026
+.Dd July 22, 2026
 .Dt KQUEUE 2
 .Os
 .Sh NAME
@@ -543,9 +543,15 @@ The exit status will be stored in
 .Va data
 in the same format as the status returned by
 .Xr wait 2 .
+.It Dv NOTE_REAP
+The process has been reaped by a call to the
+.Xr wait 2
+family of functions.
 .It Dv NOTE_FORK
 The process has called
-.Fn fork .
+.Xr fork 2
+or
+.Xr vfork 2 .
 .It Dv NOTE_EXEC
 The process has executed a new process via
 .Xr execve 2
diff --git a/lib/libsysdecode/flags.c b/lib/libsysdecode/flags.c
index f8e26e6a9dae..c46e8ec607b9 100644
--- a/lib/libsysdecode/flags.c
+++ b/lib/libsysdecode/flags.c
@@ -375,8 +375,8 @@ static struct name_table kevent_vnode_fflags[] = {
 };
 
 static struct name_table kevent_proc_fflags[] = {
-       X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR)
-       X(NOTE_CHILD) XEND
+       X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_REAP)
+       X(NOTE_TRACK) X(NOTE_TRACKERR) X(NOTE_CHILD) XEND
 };
 
 static struct name_table kevent_timer_fflags[] = {
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 8e2dd0eb3492..2a1269ec6e3c 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -445,7 +445,7 @@ filt_procattach(struct knote *kn)
        bool exiting, immediate;
 
        exiting = immediate = false;
-       if (kn->kn_sfflags & NOTE_EXIT)
+       if (kn->kn_sfflags & (NOTE_EXIT | NOTE_REAP))
                p = pfind_any(kn->kn_id);
        else
                p = pfind(kn->kn_id);
@@ -470,7 +470,7 @@ filt_procattach(struct knote *kn)
                kn->kn_flags &= ~EV_FLAG2;
                kn->kn_data = kn->kn_sdata;             /* ppid */
                kn->kn_fflags = NOTE_CHILD;
-               kn->kn_sfflags &= ~(NOTE_EXIT | NOTE_EXEC | NOTE_FORK);
+               kn->kn_sfflags &= ~NOTE_PCTRLMASK;
                immediate = true; /* Force immediate activation of child note. 
*/
        }
        /*
@@ -532,12 +532,15 @@ filt_proc(struct knote *kn, long hint)
        if ((kn->kn_sfflags & event) != 0)
                kn->kn_fflags |= kn->kn_sfflags & event;
 
+       /* Report exit status */
+       if ((kn->kn_fflags & NOTE_EXIT) != 0)
+               kn->kn_data = KW_EXITCODE(p->p_xexit, p->p_xsig);
+
        /* Process is gone, so flag the event as finished. */
-       if ((event & NOTE_EXIT) != 0) {
+       if ((event & NOTE_REAP) != 0 ||
+           ((event & NOTE_EXIT) != 0 && (kn->kn_sfflags & NOTE_REAP) == 0)) {
                kn->kn_flags |= EV_EOF | EV_ONESHOT;
                kn->kn_ptr.p_proc = NULL;
-               if (kn->kn_fflags & NOTE_EXIT)
-                       kn->kn_data = KW_EXITCODE(p->p_xexit, p->p_xsig);
                if (kn->kn_fflags == 0)
                        kn->kn_flags |= EV_DROP;
                return (1);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 8f9007752b3b..757428826f96 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1054,6 +1054,7 @@ proc_reap(struct thread *td, struct proc *p, int *status, 
int options)
        sx_xunlock(&proctree_lock);
 
        PROC_LOCK(p);
+       KNOTE_LOCKED(p->p_klist, NOTE_REAP);
        knlist_detach(p->p_klist);
        p->p_klist = NULL;
        PROC_UNLOCK(p);
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index a06d29b91ba8..953816077269 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -473,11 +473,14 @@ procdesc_kqops_event(struct knote *kn, long hint)
        if ((kn->kn_sfflags & event) != 0)
                kn->kn_fflags |= kn->kn_sfflags & event;
 
+       /* Report exit status */
+       if ((kn->kn_fflags & NOTE_EXIT) != 0)
+               kn->kn_data = pd->pd_xstat;
+
        /* Process is gone, so flag the event as finished. */
-       if (event == NOTE_EXIT) {
+       if ((event & NOTE_REAP) != 0 ||
+           ((event & NOTE_EXIT) != 0 && (kn->kn_sfflags & NOTE_REAP) == 0)) {
                kn->kn_flags |= EV_EOF | EV_ONESHOT;
-               if (kn->kn_fflags & NOTE_EXIT)
-                       kn->kn_data = pd->pd_xstat;
                if (kn->kn_fflags == 0)
                        kn->kn_flags |= EV_DROP;
                return (1);
diff --git a/sys/sys/event.h b/sys/sys/event.h
index a863cd20f45d..16fc829fc8ea 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -205,7 +205,10 @@ struct freebsd11_kevent32 {
 #define        NOTE_EXIT       0x80000000              /* process exited */
 #define        NOTE_FORK       0x40000000              /* process forked */
 #define        NOTE_EXEC       0x20000000              /* process exec'd */
-#define        NOTE_PCTRLMASK  0xf0000000              /* mask for hint bits */
+#define        NOTE_SIGNAL     0x08000000              /* process received a 
signal,
+                                                  shared with EVFIL_SIGNAL */
+#define        NOTE_REAP       0x04000000              /* process reaped */
+#define        NOTE_PCTRLMASK  0xec000000              /* mask for hint bits */
 #define        NOTE_PDATAMASK  0x000fffff              /* mask for pid */
 
 /* additional flags for EVFILT_PROC */
@@ -259,12 +262,6 @@ struct knlist {
 
 #define        KNLIST_EMPTY(list)              SLIST_EMPTY(&(list)->kl_list)
 
-/*
- * Flag indicating hint is a signal.  Used by EVFILT_SIGNAL, and also
- * shared by EVFILT_PROC  (all knotes attached to p->p_klist)
- */
-#define NOTE_SIGNAL    0x08000000
-
 /*
  * Hint values for the optional f_touch event filter.  If f_touch is not set 
  * to NULL and f_isfd is zero the f_touch filter will be called with the type

Reply via email to