diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 2adfa9cf7b9b..e4550635f8d7 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -218,8 +218,18 @@ exit1(struct thread *td, int rv) p->p_flag &= ~(P_TRACED | P_PPWAIT); SIGEMPTYSET(p->p_siglist); SIGEMPTYSET(td->td_siglist); - if (timevalisset(&p->p_realtimer.it_value)) - callout_stop(&p->p_itcallout); + + /* + * Stop the real interval timer. If the handler is currently + * executing, prevent it from rearming itself and let it finish. + */ + if (timevalisset(&p->p_realtimer.it_value) && + callout_stop(&p->p_itcallout) == 0) { + timevalclear(&p->p_realtimer.it_interval); + msleep(&p->p_itcallout, &p->p_mtx, PWAIT, "ritwait", 0); + KASSERT(!timevalisset(&p->p_realtimer.it_value), + ("realtime timer is still armed")); + } PROC_UNLOCK(p); /* diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 29de672375d1..772edc387af9 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -531,6 +531,8 @@ realitexpire(void *arg) psignal(p, SIGALRM); if (!timevalisset(&p->p_realtimer.it_interval)) { timevalclear(&p->p_realtimer.it_value); + if (p->p_flag & P_WEXIT) + wakeup(&p->p_itcallout); PROC_UNLOCK(p); return; }