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.
This commit is contained in:
parent
e9bbb44e09
commit
7bd028861b
@ -341,37 +341,73 @@ cron_tick(db)
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
cron_sync() {
|
cron_sync() {
|
||||||
|
#if 0
|
||||||
register struct tm *tm;
|
register struct tm *tm;
|
||||||
|
#endif
|
||||||
|
|
||||||
TargetTime = time((time_t*)0);
|
TargetTime = time((time_t*)0) + 1;
|
||||||
|
#if 0
|
||||||
tm = localtime(&TargetTime);
|
tm = localtime(&TargetTime);
|
||||||
TargetTime += (60 - tm->tm_sec);
|
TargetTime += (60 - tm->tm_sec);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
timeval_subtract(struct timespec *result, struct timeval *x, struct timeval *y)
|
||||||
|
{
|
||||||
|
int nsec;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cron_sleep(db)
|
cron_sleep(db)
|
||||||
cron_db *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.
|
* Loop until we reach the top of the next minute, sleep when possible.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (;;) {
|
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 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_clean(db);
|
||||||
cron_sync();
|
cron_sync();
|
||||||
continue;
|
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",
|
Debug(DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
|
||||||
getpid(), (long)TargetTime, seconds_to_wait))
|
getpid(), (long)TargetTime, seconds_to_wait))
|
||||||
|
|
||||||
@ -380,13 +416,19 @@ cron_sleep(db)
|
|||||||
* to run, break
|
* to run, break
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (seconds_to_wait <= 0)
|
if (stime.tv_sec < 0)
|
||||||
break;
|
break;
|
||||||
if (job_runqueue() == 0) {
|
if (job_runqueue() == 0) {
|
||||||
Debug(DSCH, ("[%d] sleeping for %d seconds\n",
|
Debug(DSCH, ("[%d] sleeping for %d seconds\n",
|
||||||
getpid(), seconds_to_wait))
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user