diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2017-11-23 11:25:11 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2017-11-23 11:25:11 +0000 |
| commit | ee50062cfb85553ad933db2b2e5a85fe85705d57 (patch) | |
| tree | 0d2d37bb7a06edf2ef1f981aefd6e5f9c2305ada /sys/kern/kern_procctl.c | |
| parent | a72d6c8975418bda42fe21c278fecb0ba9b4cfb4 (diff) | |
Notes
Diffstat (limited to 'sys/kern/kern_procctl.c')
| -rw-r--r-- | sys/kern/kern_procctl.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c index e875170136327..dddc6b9c1d34b 100644 --- a/sys/kern/kern_procctl.c +++ b/sys/kern/kern_procctl.c @@ -221,6 +221,8 @@ reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp) pip->pi_flags = REAPER_PIDINFO_VALID; if (proc_realparent(p2) == reap) pip->pi_flags |= REAPER_PIDINFO_CHILD; + if ((p2->p_treeflag & P_TREE_REAPER) != 0) + pip->pi_flags |= REAPER_PIDINFO_REAPER; i++; } sx_sunlock(&proctree_lock); @@ -231,19 +233,59 @@ reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp) return (error); } +static void +reap_kill_proc(struct thread *td, struct proc *p2, ksiginfo_t *ksi, + struct procctl_reaper_kill *rk, int *error) +{ + int error1; + + PROC_LOCK(p2); + error1 = p_cansignal(td, p2, rk->rk_sig); + if (error1 == 0) { + pksignal(p2, rk->rk_sig, ksi); + rk->rk_killed++; + *error = error1; + } else if (*error == ESRCH) { + rk->rk_fpid = p2->p_pid; + *error = error1; + } + PROC_UNLOCK(p2); +} + +struct reap_kill_tracker { + struct proc *parent; + TAILQ_ENTRY(reap_kill_tracker) link; +}; + +TAILQ_HEAD(reap_kill_tracker_head, reap_kill_tracker); + +static void +reap_kill_sched(struct reap_kill_tracker_head *tracker, struct proc *p2) +{ + struct reap_kill_tracker *t; + + t = malloc(sizeof(struct reap_kill_tracker), M_TEMP, M_WAITOK); + t->parent = p2; + TAILQ_INSERT_TAIL(tracker, t, link); +} + static int reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk) { struct proc *reap, *p2; ksiginfo_t ksi; - int error, error1; + struct reap_kill_tracker_head tracker; + struct reap_kill_tracker *t; + int error; sx_assert(&proctree_lock, SX_LOCKED); if (IN_CAPABILITY_MODE(td)) return (ECAPMODE); - if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG) - return (EINVAL); - if ((rk->rk_flags & ~(REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) != 0) + if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG || + (rk->rk_flags & ~(REAPER_KILL_CHILDREN | + REAPER_KILL_SUBTREE)) != 0 || (rk->rk_flags & + (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) == + (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) return (EINVAL); PROC_UNLOCK(p); reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p; @@ -255,26 +297,33 @@ reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk) error = ESRCH; rk->rk_killed = 0; rk->rk_fpid = -1; - for (p2 = (rk->rk_flags & REAPER_KILL_CHILDREN) != 0 ? - LIST_FIRST(&reap->p_children) : LIST_FIRST(&reap->p_reaplist); - p2 != NULL; - p2 = (rk->rk_flags & REAPER_KILL_CHILDREN) != 0 ? - LIST_NEXT(p2, p_sibling) : LIST_NEXT(p2, p_reapsibling)) { - if ((rk->rk_flags & REAPER_KILL_SUBTREE) != 0 && - p2->p_reapsubtree != rk->rk_subtree) - continue; - PROC_LOCK(p2); - error1 = p_cansignal(td, p2, rk->rk_sig); - if (error1 == 0) { - pksignal(p2, rk->rk_sig, &ksi); - rk->rk_killed++; - error = error1; - } else if (error == ESRCH) { - error = error1; - rk->rk_fpid = p2->p_pid; + if ((rk->rk_flags & REAPER_KILL_CHILDREN) != 0) { + for (p2 = LIST_FIRST(&reap->p_children); p2 != NULL; + p2 = LIST_NEXT(p2, p_sibling)) { + reap_kill_proc(td, p2, &ksi, rk, &error); + /* + * Do not end the loop on error, signal + * everything we can. + */ + } + } else { + TAILQ_INIT(&tracker); + reap_kill_sched(&tracker, reap); + while ((t = TAILQ_FIRST(&tracker)) != NULL) { + MPASS((t->parent->p_treeflag & P_TREE_REAPER) != 0); + TAILQ_REMOVE(&tracker, t, link); + for (p2 = LIST_FIRST(&t->parent->p_reaplist); p2 != NULL; + p2 = LIST_NEXT(p2, p_reapsibling)) { + if (t->parent == reap && + (rk->rk_flags & REAPER_KILL_SUBTREE) != 0 && + p2->p_reapsubtree != rk->rk_subtree) + continue; + if ((p2->p_treeflag & P_TREE_REAPER) != 0) + reap_kill_sched(&tracker, p2); + reap_kill_proc(td, p2, &ksi, rk, &error); + } + free(t, M_TEMP); } - PROC_UNLOCK(p2); - /* Do not end the loop on error, signal everything we can. */ } PROC_LOCK(p); return (error); |
