git: 18b6bb5231bf - main - procdesc: track count of open files
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 07 Jul 2026 01:57:15 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=18b6bb5231bf1c927a6f8de24e466764fe1f7470
commit 18b6bb5231bf1c927a6f8de24e466764fe1f7470
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-05-21 00:47:20 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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. */