Index: sys/kern/kern_ktrace.c =================================================================== --- sys/kern/kern_ktrace.c +++ sys/kern/kern_ktrace.c @@ -1224,37 +1224,58 @@ return (1); } +static struct proc * +ktr_next_descendant(struct proc *top, struct proc *p) +{ + struct proc *n; + + sx_assert(&proctree_lock, SX_LOCKED); + + LIST_FOREACH(n, &p->p_children, p_sibling) { + if (n->p_pptr == proc_realparent(n)) + return (n); + } + + for (; p != top; p = p->p_pptr) { + n = LIST_NEXT(p, p_sibling); + if (n == NULL) + continue; + + KASSERT(p->p_pptr == proc_realparent(p), + ("%s: reparented proc %p", __func__, p)); + LIST_FOREACH_FROM(n, &p->p_pptr->p_children, p_sibling) { + if (n->p_pptr == proc_realparent(n)) + return (n); + } + } + return (NULL); +} + static int ktrsetchildren(struct thread *td, struct proc *top, int ops, int facs, struct ktr_io_params *new_kiop) { - struct proc *p; - int ret = 0; + struct proc *o, *p; + int ret; - p = top; - PROC_LOCK_ASSERT(p, MA_OWNED); sx_assert(&proctree_lock, SX_LOCKED); - for (;;) { + PROC_LOCK_ASSERT(top, MA_OWNED); + + ret = 0; + for (p = top;;) { ret |= ktrops(td, p, ops, facs, new_kiop); - /* - * If this process has children, descend to them next, - * otherwise do any siblings, and if done with this level, - * follow back up the tree (but not past top). - */ - if (!LIST_EMPTY(&p->p_children)) - p = LIST_FIRST(&p->p_children); - else for (;;) { - if (p == top) - return (ret); - if (LIST_NEXT(p, p_sibling)) { - p = LIST_NEXT(p, p_sibling); - break; - } - p = p->p_pptr; + + LIST_FOREACH(o, &p->p_orphans, p_orphan) { + PROC_LOCK(o); + ret |= ktrops(td, o, ops, facs, new_kiop); } + + p = ktr_next_descendant(top, p); + if (p == NULL) + break; PROC_LOCK(p); } - /*NOTREACHED*/ + return (ret); } static void