summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2003-06-09 21:46:22 +0000
committerjhb <jhb@FreeBSD.org>2003-06-09 21:46:22 +0000
commitdc1245470e1cd07e34557602b0e3a761d3cbee7d (patch)
treebc4a40f1f1c569953d5b333f2bacb41970eecb14 /sys/kern
parent734fc8d52e1879bdc56348c84a5de9079a7a2600 (diff)
downloadFreeBSD-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/kern')
-rw-r--r--sys/kern/kern_exit.c14
-rw-r--r--sys/kern/kern_time.c2
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;
}
OpenPOWER on IntegriCloud