A fix for userland ppp's timers..

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.


>From FreeBSD


Index: timer.c
===================================================================
RCS file: /cvs/src/usr.sbin/ppp/ppp/timer.c,v
retrieving revision 1.14
diff -u -p -r1.14 timer.c
--- timer.c     17 Jul 2005 19:13:25 -0000      1.14
+++ timer.c     11 Jul 2009 01:04:31 -0000
@@ -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 *
 {
   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)

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to