From 6c067c7c3d9fcb334fcebc6d3f2e1760fc851f21 Mon Sep 17 00:00:00 2001 From: ache Date: Sat, 25 Jan 2014 02:16:09 +0000 Subject: 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 --- usr.sbin/cron/cron/cron.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/usr.sbin/cron/cron/cron.c b/usr.sbin/cron/cron/cron.c index d374319..0cdb9e3 100644 --- a/usr.sbin/cron/cron/cron.c +++ b/usr.sbin/cron/cron/cron.c @@ -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; + *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; } - - /* 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); } static void -- cgit v1.1