summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ppp
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>2009-05-26 07:32:08 +0000
committerbrian <brian@FreeBSD.org>2009-05-26 07:32:08 +0000
commita49cea262eb7aeec6c7f9eaf6c5b80911f532e9a (patch)
tree27c0bde3728f3bec772a715d3fcc7ef7a20b56e9 /usr.sbin/ppp
parent6ffe6436417e46e4117d92d087a8076e81b4fd95 (diff)
downloadFreeBSD-src-a49cea262eb7aeec6c7f9eaf6c5b80911f532e9a.zip
FreeBSD-src-a49cea262eb7aeec6c7f9eaf6c5b80911f532e9a.tar.gz
Fix a race that can stall the timer when we remove a timer that has another
timer with a <0.05 second delta next to it. This is done by avoiding the possibility of updating the first residual time delta in the timer list to zero. PR: 102747 Submitted by: Sergey Zaharchenko - doublef-ctm at yandex dot ru MFC after: 3 weeks
Diffstat (limited to 'usr.sbin/ppp')
-rw-r--r--usr.sbin/ppp/timer.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/usr.sbin/ppp/timer.c b/usr.sbin/ppp/timer.c
index 77b2af7..c1b589b7 100644
--- a/usr.sbin/ppp/timer.c
+++ b/usr.sbin/ppp/timer.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
+ * Copyright (c) 1996 - 2001, 2009 Brian Somers <brian@Awfulhak.org>
* based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
* Internet Initiative Japan, Inc (IIJ)
* All rights reserved.
@@ -94,9 +94,12 @@ timer_Start(struct pppTimer *tp)
return;
}
- /* Adjust our first delta so that it reflects what's really happening */
+ /*
+ * We just need to insert tp in the correct relative place. We don't
+ * need to adjust TimerList->rest (yet).
+ */
if (TimerList && getitimer(ITIMER_REAL, &itimer) == 0)
- TimerList->rest = RESTVAL(itimer);
+ ticks = RESTVAL(itimer) - TimerList->rest;
pt = NULL;
for (t = TimerList; t; t = t->next) {
@@ -132,6 +135,7 @@ timer_Start(struct pppTimer *tp)
static void
StopTimerNoBlock(struct pppTimer *tp)
{
+ struct itimerval itimer;
struct pppTimer *t, *pt;
/*
@@ -156,14 +160,11 @@ StopTimerNoBlock(struct pppTimer *tp)
timer_TermService(); /* Terminate Timer Service */
}
if (t->next) {
- if (!pt) { /* t (tp) was the first in the list */
- struct itimerval itimer;
-
- if (getitimer(ITIMER_REAL, &itimer) == 0)
- t->rest = RESTVAL(itimer);
- }
- t->next->rest += t->rest;
- if (!pt) /* t->next is now the first in the list */
+ if (!pt && getitimer(ITIMER_REAL, &itimer) == 0)
+ t->next->rest += RESTVAL(itimer); /* t (tp) was the first in the list */
+ else
+ t->next->rest += t->rest;
+ if (!pt && t->next->rest > 0) /* t->next is now the first in the list */
timer_InitService(1);
}
} else {
@@ -235,11 +236,19 @@ timer_Show(int LogLevel, struct prompt *prompt)
{
struct itimerval itimer;
struct pppTimer *pt;
- u_long rest = 0;
+ long rest;
- /* Adjust our first delta so that it reflects what's really happening */
+ /*
+ * Adjust the base time so that the deltas reflect what's really
+ * happening. Changing TimerList->rest might cause it to become zero
+ * (if getitimer() returns a value close to zero), and the
+ * timer_InitService() call will call setitimer() with zero it_value,
+ * stopping the itimer... so be careful!
+ */
if (TimerList && getitimer(ITIMER_REAL, &itimer) == 0)
- TimerList->rest = RESTVAL(itimer);
+ rest = RESTVAL(itimer) - TimerList->rest;
+ else
+ rest = 0;
#define SECS(val) ((val) / SECTICKS)
#define HSECS(val) (((val) % SECTICKS) * 100 / SECTICKS)
OpenPOWER on IntegriCloud