aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2026-02-16 15:20:02 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2026-02-21 09:45:47 +0000
commit0e67c3f675eab3a9c00b76e3886ace7700ef1bd4 (patch)
tree794919c6662f8d21c0d8f98236e9c98324ddc4e8
parentbe140717a0a4bbfa7176d334c36364d34a0b1bc5 (diff)
reap_kill_subtree_once(): reap_kill_proc_work() might drop proctree_lock
Due to this, restart the iteration over the p_reapsiblings if the lock was dropped. Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D55288
-rw-r--r--sys/kern/kern_procctl.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index 04c47d086677..30ab37d56877 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -280,7 +280,7 @@ reap_kill_proc_locked(struct reap_kill_proc_work *w)
}
static void
-reap_kill_proc(struct reap_kill_proc_work *w)
+reap_kill_proc(struct reap_kill_proc_work *w, bool *proctree_dropped)
{
struct pgrp *pgrp;
int xlocked;
@@ -311,6 +311,7 @@ reap_kill_proc(struct reap_kill_proc_work *w)
/* This is safe because pgrp zone is nofree. */
sx_xlock(&pgrp->pg_killsx);
sx_xunlock(&pgrp->pg_killsx);
+ *proctree_dropped = true;
if (xlocked)
sx_xlock(&proctree_lock);
else
@@ -392,7 +393,7 @@ reap_kill_subtree_once(struct thread *td, struct proc *p, struct proc *reaper,
struct reap_kill_tracker_head tracker;
struct reap_kill_tracker *t;
struct proc *p2;
- bool res;
+ bool proctree_dropped, res;
res = false;
TAILQ_INIT(&tracker);
@@ -400,6 +401,7 @@ reap_kill_subtree_once(struct thread *td, struct proc *p, struct proc *reaper,
while ((t = TAILQ_FIRST(&tracker)) != NULL) {
TAILQ_REMOVE(&tracker, t, link);
+again:
/*
* Since reap_kill_proc() drops proctree_lock sx, it
* is possible that the tracked reaper is no longer.
@@ -435,6 +437,7 @@ reap_kill_subtree_once(struct thread *td, struct proc *p, struct proc *reaper,
(P2_REAPKILLED | P2_WEXIT)) != 0)
continue;
+ proctree_dropped = false;
PROC_LOCK(p2);
if ((p2->p_flag2 & P2_WEXIT) == 0) {
_PHOLD(p2);
@@ -446,11 +449,13 @@ reap_kill_subtree_once(struct thread *td, struct proc *p, struct proc *reaper,
p2->p_flag2 |= P2_REAPKILLED;
w->target = p2;
- reap_kill_proc(w);
+ reap_kill_proc(w, &proctree_dropped);
_PRELE(p2);
}
PROC_UNLOCK(p2);
res = true;
+ if (proctree_dropped)
+ goto again;
}
reap_kill_sched_free(t);
}