Date: Tue, 09 Jun 2026 21:17:25 +0000 From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 44970244e6d8 - main - reap_kill_subtree_once: when proctree_lock is dropped, reaper might change Message-ID: <6a2882e5.2374b.62dc910b@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=44970244e6d872103f36eae34218b672b69579dd commit 44970244e6d872103f36eae34218b672b69579dd Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-06-05 23:57:16 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-06-09 21:11:45 +0000 reap_kill_subtree_once: when proctree_lock is dropped, reaper might change Recalculate it to iterate over the right set of processes. Prevent reaper' struct proc reuse by holding the tree ref on it. Since our reference is taken under the proctree lock and we know that the process is reaper, it cannot go away. The process hold count (p_lock) cannot be used there because p_lock intent is prevent exit, but reaper owns its reap-children until reaped itself, i.e. even a zombie reaper is still on duty. Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D57492 --- sys/kern/kern_procctl.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c index 1ff1b15767b5..c8d14aa2f2f6 100644 --- a/sys/kern/kern_procctl.c +++ b/sys/kern/kern_procctl.c @@ -49,6 +49,7 @@ #include <vm/pmap.h> #include <vm/vm_map.h> #include <vm/vm_extern.h> +#include <vm/uma.h> static int protect_setchild(struct thread *td, struct proc *p, int flags) @@ -366,13 +367,7 @@ reap_kill_sched(struct reap_kill_tracker_head *tracker, struct proc *p2) { struct reap_kill_tracker *t; - PROC_LOCK(p2); - if ((p2->p_flag2 & P2_WEXIT) != 0) { - PROC_UNLOCK(p2); - return; - } - _PHOLD(p2); - PROC_UNLOCK(p2); + PROC_TREE_REF(p2); t = malloc(sizeof(struct reap_kill_tracker), M_TEMP, M_WAITOK); t->parent = p2; TAILQ_INSERT_TAIL(tracker, t, link); @@ -381,7 +376,7 @@ reap_kill_sched(struct reap_kill_tracker_head *tracker, struct proc *p2) static void reap_kill_sched_free(struct reap_kill_tracker *t) { - PRELE(t->parent); + PROC_TREE_UNREF(t->parent); free(t, M_TEMP); } @@ -416,16 +411,17 @@ reap_kill_children(struct thread *td, struct proc *reaper, } static bool -reap_kill_subtree_once(struct thread *td, struct proc *p, struct proc *reaper, +reap_kill_subtree_once(struct thread *td, struct proc *p, struct proc **reaperp, struct unrhdr *pids, struct reap_kill_proc_work *w) { struct reap_kill_tracker_head tracker; struct reap_kill_tracker *t; - struct proc *p2; + struct proc *p2, *reaper, *old_reaper; bool proctree_dropped, res; res = false; TAILQ_INIT(&tracker); + reaper = *reaperp; reap_kill_sched(&tracker, reaper); while ((t = TAILQ_FIRST(&tracker)) != NULL) { TAILQ_REMOVE(&tracker, t, link); @@ -483,8 +479,24 @@ again: } PROC_UNLOCK(p2); res = true; - if (proctree_dropped) + if (proctree_dropped) { + old_reaper = reaper; + reaper = get_reaper_or_p(p); + if (old_reaper != reaper) { + *reaperp = reaper; + PROC_TREE_REF(reaper); + PROC_TREE_UNREF(old_reaper); + reap_kill_sched(&tracker, reaper); + /* + * Already scheduled kill + * actions should be kept on + * the schedule, the processes + * are inherited by the new + * reaper. + */ + } goto again; + } } reap_kill_sched_free(t); } @@ -492,7 +504,7 @@ again: } static void -reap_kill_subtree(struct thread *td, struct proc *p, struct proc *reaper, +reap_kill_subtree(struct thread *td, struct proc *p, struct proc **reaperp, struct reap_kill_proc_work *w) { struct unrhdr pids; @@ -512,7 +524,7 @@ reap_kill_subtree(struct thread *td, struct proc *p, struct proc *reaper, goto out; } PROC_UNLOCK(td->td_proc); - while (reap_kill_subtree_once(td, p, reaper, &pids, w)) + while (reap_kill_subtree_once(td, p, reaperp, &pids, w)) ; ihandle = create_iter_unr(&pids); @@ -562,6 +574,7 @@ reap_kill(struct thread *td, struct proc *p, void *data) return (EINVAL); PROC_UNLOCK(p); reaper = get_reaper_or_p(p); + ksiginfo_init(&ksi); ksi.ksi_signo = rk->rk_sig; ksi.ksi_code = SI_USER; @@ -577,7 +590,9 @@ reap_kill(struct thread *td, struct proc *p, void *data) w.ksi = &ksi; w.rk = rk; w.error = &error; - reap_kill_subtree(td, p, reaper, &w); + PROC_TREE_REF(reaper); + reap_kill_subtree(td, p, &reaper, &w); + PROC_TREE_UNREF(reaper); crfree(w.cr); } PROC_LOCK(p);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a2882e5.2374b.62dc910b>
