git: ecdc9cfea64c - stable/15 - pdwait(2): change handling of the exited processes
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 16 Aug 2026 02:47:12 UTC
The branch stable/15 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=ecdc9cfea64c987bfb1a2382b7e263016005cd54
commit ecdc9cfea64c987bfb1a2382b7e263016005cd54
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-07-28 00:31:51 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-08-16 02:41:35 +0000
pdwait(2): change handling of the exited processes
(cherry picked from commit 7da4edd300984abe67ff503828c1674a28e4b8b0)
---
sys/kern/kern_exit.c | 27 ++++++++++++++++++---------
sys/kern/sys_procdesc.c | 29 +++++++++++++++++++++++++----
sys/sys/procdesc.h | 11 +++++++++--
3 files changed, 52 insertions(+), 15 deletions(-)
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 2e8e95e33d8c..b61fb7bcf2f1 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1578,29 +1578,38 @@ kern_pdwait(struct thread *td, int fd, int *status,
("closed proc %p procdesc %p pd flags %#x",
pd->pd_proc, pd, pd->pd_flags));
+ if ((pd->pd_flags & PDF_EXITED) != 0) {
+ if ((options & WEXITED) == 0) {
+ error = ESRCH;
+ goto exit_tree_locked;
+ }
+ procdesc_fill_winfo(pd, false);
+ *status = KW_EXITCODE(pd->pd_xexit, pd->pd_xsig);
+ if (wrusage != NULL) {
+ memcpy(wrusage, &pd->pd_wrusage,
+ sizeof(*wrusage));
+ }
+ if (siginfo != NULL) {
+ memcpy(siginfo, &pd->pd_siginfo,
+ sizeof(*siginfo));
+ }
+ goto exit_tree_locked;
+ }
p = pd->pd_proc;
if (p == NULL) {
error = ESRCH;
goto exit_tree_locked;
}
PROC_LOCK(p);
+ MPASS(p->p_state != PRS_ZOMBIE);
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;
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 608771b9f38c..a605633fbca5 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -295,7 +295,8 @@ procdesc_exit(struct proc *p)
KASSERT(pd->pd_fpcount > 0, ("%s: closed procdesc %p", __func__, pd));
pd->pd_flags |= PDF_EXITED;
- pd->pd_xstat = KW_EXITCODE(p->p_xexit, p->p_xsig);
+ pd->pd_xexit = p->p_xexit;
+ pd->pd_xsig = p->p_xsig;
selwakeup(&pd->pd_selinfo);
KNOTE_LOCKED(&pd->pd_selinfo.si_note, NOTE_EXIT | NOTE_PDSIGCHLD);
@@ -337,6 +338,25 @@ procdesc_fork(struct proc *p, pid_t child_pid)
PROC_UNLOCK(p);
}
+void
+procdesc_fill_winfo(struct procdesc *pd, bool proc_locked)
+{
+ struct proc *p;
+
+ sx_assert(&proctree_lock, SA_XLOCKED);
+
+ if ((pd->pd_flags & (PDF_EXITED | PDF_EXIT_INFO)) == PDF_EXITED) {
+ pd->pd_flags |= PDF_EXIT_INFO;
+ p = pd->pd_proc;
+ if (!proc_locked)
+ PROC_LOCK(p);
+ wait_fill_siginfo(p, &pd->pd_siginfo);
+ wait_fill_wrusage(p, &pd->pd_wrusage);
+ if (!proc_locked)
+ PROC_UNLOCK(p);
+ }
+}
+
/*
* When a process descriptor is reaped, perhaps as a result of close(), release
* the process's reference on the process descriptor.
@@ -350,6 +370,7 @@ procdesc_reap(struct proc *p)
KASSERT(p->p_procdesc != NULL, ("procdesc_reap: p_procdesc == NULL"));
pd = p->p_procdesc;
+ procdesc_fill_winfo(pd, false);
pd->pd_proc = NULL;
p->p_procdesc = NULL;
procdesc_free(pd);
@@ -458,7 +479,7 @@ procdesc_poll(struct file *fp, int events, struct ucred *active_cred,
revents = 0;
pd = fp->f_data;
PROCDESC_LOCK(pd);
- if (pd->pd_flags & PDF_EXITED)
+ if ((atomic_load_int(&pd->pd_flags) & PDF_EXITED) != 0)
revents |= POLLHUP;
else
selrecord(td, &pd->pd_selinfo);
@@ -491,7 +512,7 @@ procdesc_kqops_event(struct knote *kn, long hint)
* pending.
*/
p = pd->pd_proc;
- if ((pd->pd_flags & PDF_EXITED) != 0)
+ if ((atomic_load_int(&pd->pd_flags) & PDF_EXITED) != 0)
event = NOTE_EXIT | NOTE_PDSIGCHLD;
else if ((atomic_load_int(&p->p_flag) & (P_STOPPED_SIG |
P_STOPPED_TRACE)) != 0)
@@ -509,7 +530,7 @@ procdesc_kqops_event(struct knote *kn, long hint)
/* Report exit status */
if ((kn->kn_fflags & NOTE_EXIT) != 0)
- kn->kn_data = pd->pd_xstat;
+ kn->kn_data = KW_EXITCODE(pd->pd_xexit, pd->pd_xsig);
/* Process is gone, so flag the event as finished. */
if ((event & NOTE_REAP) != 0 ||
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
index bb486d9026ba..f912f8787fd9 100644
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -71,10 +71,15 @@ struct procdesc {
/*
* In-flight data and notification of events.
*/
- int pd_flags; /* (p) PD_ flags. */
- u_short pd_xstat; /* (p) Exit status. */
+ int pd_flags; /* (t) PD_ flags. */
struct selinfo pd_selinfo; /* (p) Event notification. */
struct mtx pd_lock; /* Protect data + events. */
+
+ /* Exit status. */
+ u_int pd_xexit;
+ u_int pd_xsig;
+ struct __wrusage pd_wrusage;
+ siginfo_t pd_siginfo;
};
/*
@@ -89,6 +94,7 @@ struct procdesc {
/*
* Flags for the pd_flags field.
*/
+#define PDF_EXIT_INFO 0x00000001 /* Exit info calculated. */
#define PDF_EXITED 0x00000004 /* Process exited. */
/*
@@ -111,6 +117,7 @@ void procdesc_new(struct proc *, int);
void procdesc_finit(struct procdesc *, struct file *);
pid_t procdesc_pid(struct file *);
void procdesc_reap(struct proc *);
+void procdesc_fill_winfo(struct procdesc *pd, bool proc_locked);
int procdesc_falloc(struct thread *, struct file **, int *, int,
struct filecaps *);