diff options
author | brian <brian@FreeBSD.org> | 1999-10-15 20:44:34 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1999-10-15 20:44:34 +0000 |
commit | 179e3b22a2d301e0f4a069dd574e38b13bb06604 (patch) | |
tree | 32da7b3644fd20f9c27f725d31753554860f4ccb /usr.sbin | |
parent | cbc0d9236982fa504c7b3f06fb94b3758a089938 (diff) | |
download | FreeBSD-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.c | 32 |
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; } } } |