summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>1999-10-15 20:44:34 +0000
committerbrian <brian@FreeBSD.org>1999-10-15 20:44:34 +0000
commit179e3b22a2d301e0f4a069dd574e38b13bb06604 (patch)
tree32da7b3644fd20f9c27f725d31753554860f4ccb /usr.sbin
parentcbc0d9236982fa504c7b3f06fb94b3758a089938 (diff)
downloadFreeBSD-src-179e3b22a2d301e0f4a069dd574e38b13bb06604.zip
FreeBSD-src-179e3b22a2d301e0f4a069dd574e38b13bb06604.tar.gz
When more than one timer is expired at once, allow for the possibility
that the first timer ends up doing a timer_Stop() on the second. When this happens, remove the timer from the pending list so that we still call any subsequent timers. This bug has been here for several years, but has only been tickled recently with my device layering changes. With enormous thanks for the perseverance of: Ruslan Ermilov <ru@ucb.crimea.ua>
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ppp/timer.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/usr.sbin/ppp/timer.c b/usr.sbin/ppp/timer.c
index a56d40e..a0f039d 100644
--- a/usr.sbin/ppp/timer.c
+++ b/usr.sbin/ppp/timer.c
@@ -35,7 +35,7 @@
#include "descriptor.h"
#include "prompt.h"
-static struct pppTimer *TimerList = NULL;
+static struct pppTimer *TimerList = NULL, *ExpiredList = NULL;
static void StopTimerNoBlock(struct pppTimer *);
@@ -117,14 +117,14 @@ StopTimerNoBlock(struct pppTimer *tp)
* A STOPPED timer isn't in any list, but may have a bogus [e]next field.
* An EXPIRED timer is in the ->enext list.
*/
- if (tp->state != TIMER_RUNNING) {
- tp->next = NULL;
- tp->state = TIMER_STOPPED;
+
+ if (tp->state == TIMER_STOPPED)
return;
- }
+
pt = NULL;
for (t = TimerList; t != tp && t != NULL; t = t->next)
pt = t;
+
if (t) {
if (pt) {
pt->next = t->next;
@@ -135,10 +135,22 @@ StopTimerNoBlock(struct pppTimer *tp)
}
if (t->next)
t->next->rest += tp->rest;
- } else
- log_Printf(LogERROR, "Oops, %s timer not found!!\n", tp->name);
+ } else {
+ /* Search for any pending expired timers */
+ pt = NULL;
+ for (t = ExpiredList; t != tp && t != NULL; t = t->enext)
+ pt = t;
+
+ if (t) {
+ if (pt)
+ pt->enext = t->enext;
+ else
+ ExpiredList = t->enext;
+ } else if (tp->state == TIMER_RUNNING)
+ log_Printf(LogERROR, "Oops, %s timer not found!!\n", tp->name);
+ }
- tp->next = NULL;
+ tp->next = tp->enext = NULL;
tp->state = TIMER_STOPPED;
}
@@ -178,11 +190,11 @@ TimerService(void)
/* Process all expired timers */
while (exp) {
- next = exp->enext;
+ ExpiredList = exp->enext;
exp->enext = NULL;
if (exp->func)
(*exp->func)(exp->arg);
- exp = next;
+ exp = ExpiredList;
}
}
}
OpenPOWER on IntegriCloud