diff options
author | ache <ache@FreeBSD.org> | 2014-01-25 02:16:09 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2014-01-25 02:16:09 +0000 |
commit | 6c067c7c3d9fcb334fcebc6d3f2e1760fc851f21 (patch) | |
tree | bef31efec5573d3961cf61e55bd8100c7d400109 | |
parent | 47bb874dd7e85e87b14129162d6382b344ebdbf8 (diff) | |
download | FreeBSD-src-6c067c7c3d9fcb334fcebc6d3f2e1760fc851f21.zip FreeBSD-src-6c067c7c3d9fcb334fcebc6d3f2e1760fc851f21.tar.gz |
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
-rw-r--r-- | usr.sbin/cron/cron/cron.c | 27 |
1 files 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 |