Date: Sat, 01 Aug 2026 12:19:25 +0000 From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 7da4edd30098 - main - pdwait(2): change handling of the exited processes Message-ID: <6a6de44d.1d6b4.7899d7a8@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=7da4edd300984abe67ff503828c1674a28e4b8b0 commit 7da4edd300984abe67ff503828c1674a28e4b8b0 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-07-28 00:31:51 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-08-01 10:41:35 +0000 pdwait(2): change handling of the exited processes Instead of accessing the struct proc and gathering data from it, memoize the data needed for pdwait() on exited process in struct procdesc, at the time of process termination. This allows unlimited number of calls to pdwait(2) on procdesc for terminated process. Change the locking requirements for pd_flags to proctree_lock. This does not modify the pre-patch locking regime, but the change requires it. Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D58407 --- 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 *);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a6de44d.1d6b4.7899d7a8>
