From a471eac535f632f45345fec35628581b8931e2b1 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 7 Dec 2011 18:44:15 -0800 Subject: [PATCH] kernel - Fix alarm() timer race against exit * Stop the callout synchronously to ensure that any pending alarm timeout is completely removed before we allow a process to exit. * Add a required PHOLD() to the relaitexpire() function. --- sys/kern/kern_exit.c | 2 +- sys/kern/kern_time.c | 11 ++++++----- sys/kern/kern_timeout.c | 10 ++++++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index df1114c71e..f3ffb2bea1 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -351,7 +351,7 @@ exit1(int rv) SIGEMPTYSET(p->p_siglist); SIGEMPTYSET(lp->lwp_siglist); if (timevalisset(&p->p_realtimer.it_value)) - callout_stop(&p->p_ithandle); + callout_stop_sync(&p->p_ithandle); /* * Reset any sigio structures pointing to us as a result of diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 3058bf043a..271abcc3b3 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -759,7 +759,7 @@ sys_setitimer(struct setitimer_args *uap) lwkt_gettoken(&p->p_token); if (uap->which == ITIMER_REAL) { if (timevalisset(&p->p_realtimer.it_value)) - callout_stop(&p->p_ithandle); + callout_stop_sync(&p->p_ithandle); if (timevalisset(&aitv.it_value)) callout_reset(&p->p_ithandle, tvtohz_high(&aitv.it_value), realitexpire, p); @@ -800,12 +800,12 @@ realitexpire(void *arg) struct timeval ctv, ntv; p = (struct proc *)arg; + PHOLD(p); lwkt_gettoken(&p->p_token); ksignal(p, SIGALRM); if (!timevalisset(&p->p_realtimer.it_interval)) { timevalclear(&p->p_realtimer.it_value); - lwkt_reltoken(&p->p_token); - return; + goto done; } for (;;) { timevaladd(&p->p_realtimer.it_value, @@ -816,11 +816,12 @@ realitexpire(void *arg) timevalsub(&ntv, &ctv); callout_reset(&p->p_ithandle, tvtohz_low(&ntv), realitexpire, p); - lwkt_reltoken(&p->p_token); - return; + goto done; } } +done: lwkt_reltoken(&p->p_token); + PRELE(p); } /* diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 728b9a900b..8daf221f56 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -502,14 +502,20 @@ callout_stop_sync(struct callout *c) if (c->c_flags & CALLOUT_DID_INIT) { callout_stop(c); #ifdef SMP - sc = &softclock_pcpu_ary[c->c_gd->gd_cpuid]; + if (c->c_gd) { + sc = &softclock_pcpu_ary[c->c_gd->gd_cpuid]; + if (sc->running == c) { + while (sc->running == c) + tsleep(&sc->running, 0, "crace", 1); + } + } #else sc = &softclock_pcpu_ary[0]; -#endif if (sc->running == c) { while (sc->running == c) tsleep(&sc->running, 0, "crace", 1); } +#endif KKASSERT((c->c_flags & (CALLOUT_PENDING|CALLOUT_ACTIVE)) == 0); } } -- 2.41.0