]> err.no Git - dpkg/commitdiff
s-s-d: Fix timeout computations for --retry option
authorGuillem Jover <guillem@debian.org>
Tue, 22 Jan 2008 21:36:06 +0000 (23:36 +0200)
committerGuillem Jover <guillem@debian.org>
Tue, 22 Jan 2008 21:36:06 +0000 (23:36 +0200)
This has not worked properly for a long time (maybe never), but came to
light due to #460903's fix. Closes: #462104

ChangeLog
debian/changelog
utils/start-stop-daemon.c

index c9ca1a80bfe1e9e1d79ed4b08d0b21849014dfe3..0e75f1a0264de9790940c1f8c11df4b6c143fca9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-01-22  Guillem Jover  <guillem@debian.org>
+
+       * utils/start-stop-daemon.c (tvselector): Remove typedef.
+       (tvselector_sec): Remove function.
+       (tvselector_usec): Likewise.
+       (TVCALC_ELEM): Remove macro.
+       (TVCALC): Likewise.
+       (tsub): New function.
+       (tmul): Likewise.
+       (run_stop_schedule): Use tsub and tmul instead of TVCALC. Make sure
+       the time is not negative.
+
 2008-01-22  Guillem Jover  <guillem@debian.org>
 
        * utils/start-stop-daemon.c (main): Only call initgroups if changeuser
index 6e689a4410c96010cd8c914329976e8bac9cfb78..c165a3ba5240cd18d02843e044a481aa37d0919c 100644 (file)
@@ -11,6 +11,9 @@ dpkg (1.14.16.3) UNRELEASED; urgency=low
   * Fix segfault in start-stop-daemon when using --group w/o --chuid (as
     a side effect, using --group alone works for the first time in years).
     Closes: #462072
+  * Fix timeout computations for start-stop-daemon --retry option. This has
+    not worked properly for a long time (maybe never), but came to light
+    due to #460903's fix. Closes: #462104
 
  -- Raphael Hertzog <hertzog@debian.org>  Tue, 22 Jan 2008 18:15:42 +0100
 
index ef9b4170e4eb9c9cd4bdcee353e0f7426a884749..79d07c349595d94cf01622e174e159049a3823b8 100644 (file)
@@ -185,48 +185,6 @@ static void fatal(const char *format, ...)
 static void badusage(const char *msg)
        NONRETURNING;
 
-/* This next part serves only to construct the TVCALC macro, which
- * is used for doing arithmetic on struct timeval's.  It works like this:
- *   TVCALC(result, expression);
- * where result is a struct timeval (and must be an lvalue) and
- * expression is the single expression for both components.  In this
- * expression you can use the special values TVELEM, which when fed a
- * const struct timeval* gives you the relevant component, and
- * TVADJUST.  TVADJUST is necessary when subtracting timevals, to make
- * it easier to renormalise.  Whenver you subtract timeval elements,
- * you must make sure that TVADJUST is added to the result of the
- * subtraction (before any resulting multiplication or what have you).
- * TVELEM must be linear in TVADJUST.
- */
-typedef long tvselector(const struct timeval*);
-
-static long
-tvselector_sec(const struct timeval *tv)
-{
-       return tv->tv_sec;
-}
-
-static long
-tvselector_usec(const struct timeval *tv)
-{
-       return tv->tv_usec;
-}
-
-#define TVCALC_ELEM(result, expr, sec, adj)                           \
-{                                                                    \
-  const long TVADJUST = adj;                                         \
-  long (*const TVELEM)(const struct timeval *) = tvselector_##sec;    \
-  (result).tv_##sec = (expr);                                        \
-}
-#define TVCALC(result, expr)                                         \
-do {                                                                 \
-  TVCALC_ELEM(result, expr, sec, (-1));                                      \
-  TVCALC_ELEM(result, expr, usec, (+1000000));                       \
-  (result).tv_sec += (result).tv_usec / 1000000;                     \
-  (result).tv_usec %= 1000000;                                       \
-} while (0)
-
-
 static void
 fatal(const char *format, ...)
 {
@@ -257,6 +215,29 @@ xgettimeofday(struct timeval *tv)
        if (gettimeofday(tv, NULL) != 0)
                fatal("gettimeofday failed: %s", strerror(errno));
 }
+
+static void
+tsub(struct timeval *r, struct timeval *a, struct timeval *b)
+{
+       r->tv_sec = (time_t)(a->tv_sec - b->tv_sec);
+       r->tv_usec = (suseconds_t)(a->tv_usec - b->tv_usec);
+       if (r->tv_usec < 0) {
+               --r->tv_sec;
+               r->tv_usec += 1000000;
+       }
+}
+
+static void
+tmul(struct timeval *a, int b)
+{
+       a->tv_sec *= b;
+       a->tv_usec *= b;
+       if (a->tv_usec >= 1000000) {
+               ++a->tv_sec;
+               a->tv_usec -= 1000000;
+       }
+}
+
 static long
 get_open_fd_max(void)
 {
@@ -1219,10 +1200,12 @@ run_stop_schedule(void)
                                if (ratio < 10)
                                        ratio++;
 
-                               TVCALC(interval, TVELEM(&after) * ratio -
-                                                TVELEM(&before) + TVADJUST);
-                               TVCALC(maxinterval, TVELEM(&stopat) -
-                                                   TVELEM(&after) + TVADJUST);
+                               tsub(&maxinterval, &stopat, &after);
+                               tsub(&interval, &after, &before);
+                               tmul(&interval, ratio);
+
+                               if (interval.tv_sec < 0 || interval.tv_usec < 0)
+                                       interval.tv_sec = interval.tv_usec = 0;
 
                                if (timercmp(&interval, &maxinterval, >))
                                        interval = maxinterval;