diff --git a/lib/libsys/kqueue.2 b/lib/libsys/kqueue.2 --- 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,6 +543,8 @@ .Va data in the same format as the status returned by .Xr wait 2 . +.It Dv NOTE_REAP +The process has been reaped. .It Dv NOTE_FORK The process has called .Fn fork . diff --git a/lib/libsysdecode/flags.c b/lib/libsysdecode/flags.c --- a/lib/libsysdecode/flags.c +++ b/lib/libsysdecode/flags.c @@ -377,7 +377,7 @@ }; static struct name_table kevent_proc_fflags[] = { - X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_PDSIGCHLD) + X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_PDSIGCHLD) X(NOTE_REAP) X(NOTE_TRACK) X(NOTE_TRACKERR) X(NOTE_CHILD) XEND }; diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -445,7 +445,7 @@ 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 @@ 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 @@ if (kn->kn_sfflags & event) kn->kn_fflags |= 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) { + 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 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1054,6 +1054,7 @@ 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 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -521,11 +521,14 @@ if (kn->kn_sfflags & event) kn->kn_fflags |= 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) != 0) { + 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 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -209,7 +209,8 @@ #define NOTE_EXEC 0x20000000 /* proc: process exec'd */ #define NOTE_PDSIGCHLD 0x10000000 /* procdesc: pdwait() info available */ -#define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ +#define NOTE_REAP 0x08000000 /* process reaped */ +#define NOTE_PCTRLMASK 0xf8000000 /* mask for hint bits */ #define NOTE_PDATAMASK 0x000fffff /* mask for pid */ /* additional flags for EVFILT_PROC */