DF-2688 / fix.diff
--- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -1825,13 +1825,33 @@ info.bigsize = 0; allproc_scan(vm_pageout_scan_callback, &info, 0); if (info.bigproc != NULL) { + struct proc *bp = info.bigproc; + struct lwp *blp; + kprintf("Try to kill process %d %s\n", - info.bigproc->p_pid, info.bigproc->p_comm); - info.bigproc->p_nice = PRIO_MIN; - info.bigproc->p_usched->resetpriority( - FIRST_LWP_IN_PROC(info.bigproc)); - atomic_set_int(&info.bigproc->p_flags, P_LOWMEMKILL); - killproc(info.bigproc, "out of swap space"); + bp->p_pid, bp->p_comm); + + /* + * Re-acquire the token and re-validate liveness. + * The callback ran under p_token but released it + * before we got here; the proc may be exiting or + * already zombified, and FIRST_LWP_IN_PROC() is + * an un-serialized rb-tree walk if p_token is not + * held. + */ + lwkt_gettoken(&bp->p_token); + if (bp->p_stat == SACTIVE || bp->p_stat == SSTOP || + bp->p_stat == SCORE) { + bp->p_nice = PRIO_MIN; + blp = FIRST_LWP_IN_PROC(bp); + if (blp) + bp->p_usched->resetpriority(blp); + atomic_set_int(&bp->p_flags, P_LOWMEMKILL); + lwkt_reltoken(&bp->p_token); + killproc(bp, "out of swap space"); + } else { + lwkt_reltoken(&bp->p_token); + } wakeup(&vmstats.v_free_count); PRELE(info.bigproc); } |