]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Use clock_gettime() instead of time() in epggrab.c
authorMichael Marley <michael@michaelmarley.com>
Sat, 11 Dec 2021 23:09:47 +0000 (18:09 -0500)
committerFlole998 <Flole998@users.noreply.github.com>
Sun, 12 Dec 2021 22:06:16 +0000 (23:06 +0100)
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.

src/epggrab.c

index f14d53a438076fc828e70212729685a1e7b3f1f7..6e419f071a1dec6982f5743fb8f99d4a07da5b52 100644 (file)
@@ -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, &current_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) */