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. */
 

Reply via email to