The branch stable/14 has been updated by des:

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

commit b58c9e8cf6acef2774ebb87dd79eecfa31618d6a
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:13 +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/libc/sys/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/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index d6e949baa24c..e4e4c85d8a77 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd March 26, 2023
+.Dd July 22, 2026
 .Dt KQUEUE 2
 .Os
 .Sh NAME
@@ -516,9 +516,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 32829d35dbe0..018dfef5f5c2 100644
--- a/lib/libsysdecode/flags.c
+++ b/lib/libsysdecode/flags.c
@@ -367,8 +367,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 e2f44aea27b4..a735dfaa97df 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -421,7 +421,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);
@@ -446,7 +446,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. 
*/
        }
        /*
@@ -508,12 +508,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 baa5cad2bdc8..3cfb55fe3711 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -987,6 +987,7 @@ proc_reap(struct thread *td, struct proc *p, int *status, 
int options)
        proc_id_clear(PROC_ID_PID, p->p_pid);
 
        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 f1aeb4066fa4..c6781aac2523 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -468,11 +468,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 a1cd224a960e..246ebdedd004 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -203,7 +203,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 */
@@ -248,12 +251,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