diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2026-02-16 15:20:02 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2026-02-21 09:45:47 +0000 |
| commit | 0e67c3f675eab3a9c00b76e3886ace7700ef1bd4 (patch) | |
| tree | 794919c6662f8d21c0d8f98236e9c98324ddc4e8 | |
| parent | be140717a0a4bbfa7176d334c36364d34a0b1bc5 (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.c | 11 |
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); } |
