The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=18b6bb5231bf1c927a6f8de24e466764fe1f7470
commit 18b6bb5231bf1c927a6f8de24e466764fe1f7470 Author: Konstantin Belousov <[email protected]> AuthorDate: 2026-05-21 00:47:20 +0000 Commit: Konstantin Belousov <[email protected]> CommitDate: 2026-07-07 01:24:02 +0000 procdesc: track count of open files Introduce pd_fpcount that counts the number of file references to the procdesc. Remove the PDF_CLOSED flag, now it is expressed as pd_fpcount == 0. Only send SIGKILL and clear pointers when we are closing the last file referencing procdesc. This should be nop until the next commit. Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D57124 --- sys/kern/kern_exit.c | 4 ++-- sys/kern/sys_procdesc.c | 17 +++++++++++------ sys/sys/procdesc.h | 4 +++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 8f9007752b3b..db8882d70041 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1573,8 +1573,8 @@ kern_pdwait(struct thread *td, int fd, int *status, for (;;) { /* We own a reference on the procdesc file. */ - KASSERT((pd->pd_flags & PDF_CLOSED) == 0, - ("PDF_CLOSED proc %p procdesc %p pd flags %#x", + KASSERT(pd->pd_fpcount > 0, + ("closed proc %p procdesc %p pd flags %#x", p, pd, pd->pd_flags)); sx_xlock(&proctree_lock); diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c index e6174ea3cbb9..c5be98f66749 100644 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -219,6 +219,7 @@ procdesc_alloc(int flags) * struct file, and the other from their struct proc. */ refcount_init(&pd->pd_refcount, 2); + pd->pd_fpcount = 1; return (pd); } @@ -293,8 +294,8 @@ procdesc_free(struct procdesc *pd) if (refcount_release(&pd->pd_refcount)) { KASSERT(pd->pd_proc == NULL, ("procdesc_free: pd_proc != NULL")); - KASSERT((pd->pd_flags & PDF_CLOSED), - ("procdesc_free: !PDF_CLOSED")); + KASSERT(pd->pd_fpcount == 0, + ("procdesc_free: not closed %p %d", pd, pd->pd_fpcount)); if (pd->pd_pid != -1) proc_id_clear(PROC_ID_PID, pd->pd_pid); @@ -322,7 +323,7 @@ procdesc_exit(struct proc *p) pd = p->p_procdesc; PROCDESC_LOCK(pd); - KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr == p->p_reaper, + KASSERT(pd->pd_fpcount > 0 || p->p_pptr == p->p_reaper, ("procdesc_exit: closed && parent not reaper")); pd->pd_flags |= PDF_EXITED; @@ -334,7 +335,7 @@ procdesc_exit(struct proc *p) * Clean up the procdesc now rather than letting it happen during * that reap. */ - if (pd->pd_flags & PDF_CLOSED) { + if (pd->pd_fpcount == 0) { PROCDESC_UNLOCK(pd); pd->pd_proc = NULL; p->p_procdesc = NULL; @@ -388,7 +389,8 @@ procdesc_close(struct file *fp, struct thread *td) sx_xlock(&proctree_lock); PROCDESC_LOCK(pd); - pd->pd_flags |= PDF_CLOSED; + MPASS(pd->pd_fpcount > 0); + pd->pd_fpcount--; PROCDESC_UNLOCK(pd); p = pd->pd_proc; if (p == NULL) { @@ -408,7 +410,7 @@ procdesc_close(struct file *fp, struct thread *td) * calls back into procdesc_reap(). */ proc_reap(curthread, p, NULL, 0); - } else { + } else if (pd->pd_fpcount == 0) /* last procdesc */ { /* * If the process is not yet dead, we need to kill it, * but we can't wait around synchronously for it to go @@ -438,6 +440,9 @@ procdesc_close(struct file *fp, struct thread *td) kern_psignal(p, SIGKILL); PROC_UNLOCK(p); sx_xunlock(&proctree_lock); + } else { + PROC_UNLOCK(p); + sx_xunlock(&proctree_lock); } } diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h index a6be5dbe576c..08b563828b95 100644 --- a/sys/sys/procdesc.h +++ b/sys/sys/procdesc.h @@ -51,6 +51,8 @@ * (r) - Atomic reference count. * (s) - Protected by selinfo. * (t) - Protected by the proctree_lock + * (p|t) - Both procree_lock and process descriptor must be locked + * for pd_fpcount */ struct proc; struct sigio; @@ -63,6 +65,7 @@ struct procdesc { struct proc *pd_proc; /* (t) Process. */ pid_t pd_pid; /* (c) Cached pid. */ u_int pd_refcount; /* (r) Reference count. */ + u_int pd_fpcount; /* (p|t) files referencing me */ /* * In-flight data and notification of events. @@ -85,7 +88,6 @@ struct procdesc { /* * Flags for the pd_flags field. */ -#define PDF_CLOSED 0x00000001 /* Descriptor has closed. */ #define PDF_EXITED 0x00000004 /* Process exited. */ #define PDF_DAEMON 0x00000008 /* Don't exit when procdesc closes. */
