From: Michael Marley Date: Sat, 11 Dec 2021 23:09:47 +0000 (-0500) Subject: Use clock_gettime() instead of time() in epggrab.c X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ed7d10ac2e895080d08587048ac5a24a2f9fae3;p=thirdparty%2Ftvheadend.git Use clock_gettime() instead of time() in epggrab.c time() appears to return a slightly-rounded value as compared to functions that return higher-precision time like gettimeofday() and timespec_get(). Specifically, when gettimeofday() would return a value with a low number in tv_usec, time() will return one fewer seconds than tv_sec from gettimeofday(). The difference is minute and probably doesn't cause an issue in most cases, but here in epggrab.c the time of the next cron run is calculated immediately after the previous run fires. In this case, the value of time() is actually one second lower than the specified cron run time. This value is then passed into cron_multi_next(), which correctly sets the next cron run to the current time. Therefore, as soon as the EPG grab completes, cron triggers again and re-runs it. Using the more precise values from gettimeofday() (by way of clock_gettime()) solves this problem and ensures that cron runs only once. This solves #5545 and #5364. --- diff --git a/src/epggrab.c b/src/epggrab.c index f14d53a43..6e419f071 100644 --- a/src/epggrab.c +++ b/src/epggrab.c @@ -94,42 +94,46 @@ static void *_epggrab_internal_thread( void *aux ) { epggrab_module_t *mod; int err, confver; - struct timespec ts; + struct timespec cron_next, current_time; time_t t; confver = epggrab_conf.int_initial ? -1 /* force first run */ : epggrab_confver; /* Setup timeout */ - ts.tv_nsec = 0; - ts.tv_sec = time(NULL) + 120; + clock_gettime(CLOCK_REALTIME, &cron_next); + cron_next.tv_nsec = 0; + cron_next.tv_sec += 120; /* Time for other jobs */ while (atomic_get(&epggrab_running)) { tvh_mutex_lock(&epggrab_mutex); err = ETIMEDOUT; while (atomic_get(&epggrab_running)) { - err = tvh_cond_timedwait_ts(&epggrab_cond, &epggrab_mutex, &ts); + err = tvh_cond_timedwait_ts(&epggrab_cond, &epggrab_mutex, &cron_next); if (err == ETIMEDOUT) break; } tvh_mutex_unlock(&epggrab_mutex); if (err == ETIMEDOUT) break; } - time(&ts.tv_sec); + clock_gettime(CLOCK_REALTIME, &cron_next); + cron_next.tv_nsec = 0; while (atomic_get(&epggrab_running)) { /* Check for config change */ tvh_mutex_lock(&epggrab_mutex); while (atomic_get(&epggrab_running) && confver == epggrab_confver) { - err = tvh_cond_timedwait_ts(&epggrab_cond, &epggrab_mutex, &ts); + err = tvh_cond_timedwait_ts(&epggrab_cond, &epggrab_mutex, &cron_next); if (err == ETIMEDOUT) break; } confver = epggrab_confver; - if (!cron_multi_next(epggrab_cron_multi, time(NULL), &t)) - ts.tv_sec = t; + + clock_gettime(CLOCK_REALTIME, ¤t_time); + if (!cron_multi_next(epggrab_cron_multi, current_time.tv_sec, &t)) + cron_next.tv_sec = t; else - ts.tv_sec += 60; + cron_next.tv_sec += 60; tvh_mutex_unlock(&epggrab_mutex); /* Run grabber(s) */