Author: ache
Date: Sat Jan 25 02:16:09 2014
New Revision: 261146
URL: http://svnweb.freebsd.org/changeset/base/261146

Log:
  Bad timespec_subtract() calculations produce negative tv_nsec on i386
  which cause EINVAL returned from nanosleep() which cause loop in
  cron_sleep() and making all cron jobs to start about 30 seconds earlier
  (which cause f.e. logfiles rotation by newsyslog delayed by 1 hour).
  
  Use simple and proved calculations from kernel's timespecsub() instead.
  
  MFC after:      3 days

Modified:
  head/usr.sbin/cron/cron/cron.c

Modified: head/usr.sbin/cron/cron/cron.c
==============================================================================
--- head/usr.sbin/cron/cron/cron.c      Sat Jan 25 01:58:15 2014        
(r261145)
+++ head/usr.sbin/cron/cron/cron.c      Sat Jan 25 02:16:09 2014        
(r261146)
@@ -376,30 +376,17 @@ cron_sync(int secres) {
        }
 }
 
-static int
+static void
 timespec_subtract(struct timespec *result, struct timespec *x,
     struct timespec *y)
 {
-       time_t nsec;
-
-       /* Perform the carry for the later subtraction by updating y. */
-       if (x->tv_nsec < y->tv_nsec) {
-               nsec = (y->tv_nsec - x->tv_nsec) / 10000000 + 1;
-               y->tv_nsec -= 1000000000 * nsec;
-               y->tv_sec += nsec;
-       }
-       if (x->tv_nsec - y->tv_nsec > 1000000000) {
-               nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
-               y->tv_nsec += 1000000000 * nsec;
-               y->tv_sec -= nsec;
-       }
-     
-       /* tv_nsec is certainly positive. */
-       result->tv_sec = x->tv_sec - y->tv_sec;
-       result->tv_nsec = x->tv_nsec - y->tv_nsec;
-     
-       /* Return True if result is negative. */
-       return (x->tv_sec < y->tv_sec);
+       *result = *x;
+       result->tv_sec -= y->tv_sec;
+       result->tv_nsec -= y->tv_nsec;
+       if (result->tv_nsec < 0) {
+               result->tv_sec--;
+               result->tv_nsec += 1000000000;
+       }
 }
 
 static void
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to