diff options
author | jhb <jhb@FreeBSD.org> | 2003-06-09 21:46:22 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2003-06-09 21:46:22 +0000 |
commit | dc1245470e1cd07e34557602b0e3a761d3cbee7d (patch) | |
tree | bc4a40f1f1c569953d5b333f2bacb41970eecb14 /sys | |
parent | 734fc8d52e1879bdc56348c84a5de9079a7a2600 (diff) | |
download | FreeBSD-src-dc1245470e1cd07e34557602b0e3a761d3cbee7d.zip FreeBSD-src-dc1245470e1cd07e34557602b0e3a761d3cbee7d.tar.gz |
Wait for the real interval timer callout handler to finish executing if it
is currently executing when we try to remove it in exit1(). Without this,
it was possible for the callout to bogusly rearm itself and eventually
refire after the process had been free'd resulting in a panic.
PR: kern/51964
Reported by: Jilles Tjoelker <jilles@stack.nl>
Reviewed by: tegge, bde
Diffstat (limited to 'sys')
-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; } |