svn commit: r241625 - head/usr.sbin/cron/cron
Andrey Zonov
zont at FreeBSD.org
Wed Oct 17 07:58:28 UTC 2012
On 10/17/12 4:44 AM, Maxim Sobolev wrote:
> Author: sobomax
> Date: Wed Oct 17 00:44:34 2012
> New Revision: 241625
> URL: http://svn.freebsd.org/changeset/base/241625
>
> Log:
> o Use nanosleep(2) to sleep exact amount of time till the next second,
> not multiple of 1 second, which results in actual time to drift back
> and forth every run within 1 second of the actual action has
> been set for.
>
> Suggested by: Ian Lepore
>
> o Schedule the first run in 1 second after starting up, not on the
> boundary of the next minute, which results in the every_second jobs
> not being run.
>
> Modified:
> head/usr.sbin/cron/cron/cron.c
>
> Modified: head/usr.sbin/cron/cron/cron.c
> ==============================================================================
> --- head/usr.sbin/cron/cron/cron.c Wed Oct 17 00:33:10 2012 (r241624)
> +++ head/usr.sbin/cron/cron/cron.c Wed Oct 17 00:44:34 2012 (r241625)
> @@ -341,37 +341,73 @@ cron_tick(db)
> */
> static void
> cron_sync() {
> +#if 0
> register struct tm *tm;
> +#endif
>
> - TargetTime = time((time_t*)0);
> + TargetTime = time((time_t*)0) + 1;
> +#if 0
> tm = localtime(&TargetTime);
> TargetTime += (60 - tm->tm_sec);
> +#endif
> }
>
> +static int
This should be type of time_t.
> +timeval_subtract(struct timespec *result, struct timeval *x, struct timeval *y)
> +{
> + int nsec;
And this should be suseconds_t.
> +
> + /* Perform the carry for the later subtraction by updating y. */
> + if (x->tv_usec < y->tv_usec) {
> + nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
> + y->tv_usec -= 1000000 * nsec;
> + y->tv_sec += nsec;
> + }
> + if (x->tv_usec - y->tv_usec > 1000000) {
> + nsec = (x->tv_usec - y->tv_usec) / 1000000;
> + y->tv_usec += 1000000 * nsec;
> + y->tv_sec -= nsec;
> + }
> +
> + /* tv_nsec is certainly positive. */
> + result->tv_sec = x->tv_sec - y->tv_sec;
> + result->tv_nsec = (x->tv_usec - y->tv_usec) * 1000;
> +
> + /* Return difference in seconds */
> + return (x->tv_sec - y->tv_sec);
> +}
May be it's better to use timersub() and TIMEVAL_TO_TIMESPEC()?
>
> static void
> cron_sleep(db)
> cron_db *db;
> {
> - int seconds_to_wait = 0;
> + int seconds_to_wait;
> + int rval;
> + struct timeval ctime, ttime;
> + struct timespec stime, remtime;
>
> /*
> * Loop until we reach the top of the next minute, sleep when possible.
> */
>
> for (;;) {
> - seconds_to_wait = (int) (TargetTime - time((time_t*)0));
> + gettimeofday(&ctime, NULL);
> + ttime.tv_sec = TargetTime;
> + ttime.tv_usec = 0;
> + timeval_subtract(&stime, &ttime, &ctime);
>
> /*
> * If the seconds_to_wait value is insane, jump the cron
> */
>
> - if (seconds_to_wait < -600 || seconds_to_wait > 600) {
> + if (stime.tv_sec < -600 || stime.tv_sec > 600) {
> cron_clean(db);
> cron_sync();
> continue;
> }
>
> + seconds_to_wait = (stime.tv_nsec > 0) ? stime.tv_sec + 1 : stime.tv_sec;
> +
> Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
> getpid(), (long)TargetTime, seconds_to_wait))
>
> @@ -380,13 +416,19 @@ cron_sleep(db)
> * to run, break
> */
>
> - if (seconds_to_wait <= 0)
> + if (stime.tv_sec < 0)
> break;
> if (job_runqueue() == 0) {
> Debug(DSCH, ("[%d] sleeping for %d seconds\n",
> getpid(), seconds_to_wait))
>
> - sleep(seconds_to_wait);
> + for (;;) {
> + rval = nanosleep(&stime, &remtime);
> + if (rval == 0 || errno != EINTR)
> + break;
> + stime.tv_sec = remtime.tv_sec;
> + stime.tv_nsec = remtime.tv_nsec;
> + }
> }
> }
> }
>
--
Andrey Zonov
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 535 bytes
Desc: OpenPGP digital signature
URL: <http://lists.freebsd.org/pipermail/svn-src-head/attachments/20121017/fe6503d4/attachment.sig>
More information about the svn-src-head
mailing list