diff options
author | ache <ache@FreeBSD.org> | 2014-01-28 13:29:54 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2014-01-28 13:29:54 +0000 |
commit | 1626ab813a29f8b30941a7b807d6da5e3bd395d5 (patch) | |
tree | 8c6a003f373aabc140a3d2b62d8b330c4aa809dc | |
parent | 782dc633da2fa3336558b8b143198f7f95bfab13 (diff) | |
download | FreeBSD-src-1626ab813a29f8b30941a7b807d6da5e3bd395d5.zip FreeBSD-src-1626ab813a29f8b30941a7b807d6da5e3bd395d5.tar.gz |
MFC: r261146
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.
-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 |