Просмотр исходного кода

s-s-d: Fix timeout computations for --retry option

This has not worked properly for a long time (maybe never), but came to
light due to #460903's fix. Closes: #462104
Guillem Jover лет назад: 18
Родитель
Сommit
fb08b88f65
3 измененных файлов с 44 добавлено и 46 удалено
  1. 12 0
      ChangeLog
  2. 3 0
      debian/changelog
  3. 29 46
      utils/start-stop-daemon.c

+ 12 - 0
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

+ 3 - 0
debian/changelog

@@ -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
 

+ 29 - 46
utils/start-stop-daemon.c

@@ -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;