From c459aa5155f6409a9c4a97af5940b2fcfdb4758c Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 10 Jan 2016 16:00:27 +0100 Subject: [PATCH] sectionsd: try to avoid setting bogus time I recently saw spurious cases of the DVB time being off 30 minutes. I am still investigating if this is a driver issue or something else, but for now, if the time diff is bigger than 120 seconds, ask for a second opinion about the current dvb time before stepping the clock. Additionally, ignore time differences of less than one second (the granularity of DVB time stamps is one second anyway) Origin commit data ------------------ Commit: https://github.com/neutrino-images/ni-neutrino/commit/e85565fd9666725e645f2b2a4fd4cf54ad9993cf Author: Stefan Seyfried Date: 2016-01-10 (Sun, 10 Jan 2016) --- src/eitd/eitd.h | 2 +- src/eitd/sectionsd.cpp | 34 +++++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/eitd/eitd.h b/src/eitd/eitd.h index 9018b4b2c..a082b401f 100644 --- a/src/eitd/eitd.h +++ b/src/eitd/eitd.h @@ -296,7 +296,7 @@ class CTimeThread : public CSectionThread OpenThreads::Condition time_cond; void sendTimeEvent(bool dvb, time_t tim = 0); - void setSystemTime(time_t tim); + bool setSystemTime(time_t tim, bool force = false); void run(); public: CTimeThread(); diff --git a/src/eitd/sectionsd.cpp b/src/eitd/sectionsd.cpp index 66371d789..d521cf7ad 100644 --- a/src/eitd/sectionsd.cpp +++ b/src/eitd/sectionsd.cpp @@ -5,7 +5,7 @@ * Copyright (C) 2001 by fnbrd (fnbrd@gmx.de) * Homepage: http://dbox2.elxsi.de * - * Copyright (C) 2008-2013 Stefan Seyfried + * Copyright (C) 2008-2016 Stefan Seyfried * * Copyright (C) 2011-2012 CoolStream International Ltd * @@ -1380,7 +1380,7 @@ void CTimeThread::waitForTimeset(void) time_mutex.unlock(); } -void CTimeThread::setSystemTime(time_t tim) +bool CTimeThread::setSystemTime(time_t tim, bool force) { struct timeval tv; struct tm t; @@ -1388,6 +1388,7 @@ void CTimeThread::setSystemTime(time_t tim) gettimeofday(&tv, NULL); timediff = int64_t(tim * 1000000 - (tv.tv_usec + tv.tv_sec * 1000000)); localtime_r(&tv.tv_sec, &t); + int absdiff = abs(tim - tv.tv_sec); xprintf("%s: timediff %" PRId64 ", current: %02d.%02d.%04d %02d:%02d:%02d, dvb: %s", name.c_str(), timediff, @@ -1399,9 +1400,9 @@ void CTimeThread::setSystemTime(time_t tim) return; } #endif - if (timediff == 0) /* very unlikely... :-) */ - return; - if (timeset && abs(tim - tv.tv_sec) < 120) { /* abs() is int */ + if (absdiff < 1) /* do not bother for differences less than one second */ + return true; + if (absdiff < 120) { struct timeval oldd; tv.tv_sec = time_t(timediff / 1000000LL); tv.tv_usec = suseconds_t(timediff % 1000000LL); @@ -1411,14 +1412,21 @@ void CTimeThread::setSystemTime(time_t tim) xprintf("difference is < 120s, using adjtime(%d, %d). oldd(%d, %d)\n", (int)tv.tv_sec, (int)tv.tv_usec, (int)oldd.tv_sec, (int)oldd.tv_usec); timediff = 0; - return; + return true; } + } else if (timeset && ! force) { + xprintf("difference is > 120s, try again and set 'force=true'\n"); + return false; } + /* still fall through if adjtime() failed */ tv.tv_sec = tim; tv.tv_usec = 0; - if (settimeofday(&tv, NULL) < 0) - perror("[sectionsd] settimeofday"); + if (settimeofday(&tv, NULL) == 0) + return true; + + perror("[sectionsd] settimeofday"); + return false; } void CTimeThread::addFilters() @@ -1430,6 +1438,7 @@ void CTimeThread::addFilters() void CTimeThread::run() { time_t dvb_time = 0; + bool retry = false; /* if time seems fishy, set to true and try again */ xprintf("%s::run:: starting, pid %d (%lu)\n", name.c_str(), getpid(), pthread_self()); const char *tn = ("sd:" + name).c_str(); set_threadname(tn); @@ -1503,7 +1512,14 @@ void CTimeThread::run() sleep_time = ntprefresh * 60; if(success) { if(dvb_time) { - setSystemTime(dvb_time); + bool ret = setSystemTime(dvb_time, retry); + if (! ret) { + xprintf("%s: time looks wrong, trying again\n", name.c_str()); + sendToSleepNow = false; + retry = true; + continue; + } + retry = false; /* retry a second time immediately after start, to get TOT ? */ if(first_time) sleep_time = 5;