diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_exit.c | 14 | ||||
-rw-r--r-- | sys/kern/kern_time.c | 2 |
2 files changed, 14 insertions, 2 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 2adfa9c..e455063 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 29de672..772edc3 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; } |