From: Hattink, Tjalling [FINT] Date: Wed, 28 May 2014 11:54:27 +0000 (+0200) Subject: rtc: more reliable method of reading rtc for initial trim X-Git-Tag: 1.30-pre1~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ed9853bcc6a2e75749dd8a8153cdfb9efd8b236;p=thirdparty%2Fchrony.git rtc: more reliable method of reading rtc for initial trim When chrony reads in the linux rtc for the first time to trim the system clock, it only reads it once. As it is possible that the rtc updates itself during the read operation, the reported rtc time could be false. To prevent this I've added a loop that reads the rtc clock twice, if the seconds do not match retry the two read operations. If they match you can assume the read operation was successful. This is based on the hwclock implementation of reading the rtc clock from the util-linux package. --- diff --git a/rtc_linux.c b/rtc_linux.c index 91b0cacc..198e3b7c 100644 --- a/rtc_linux.c +++ b/rtc_linux.c @@ -971,7 +971,7 @@ void RTC_Linux_TimePreInit(void) { int fd, status; - struct rtc_time rtc_raw; + struct rtc_time rtc_raw, rtc_raw_retry; struct tm rtc_tm; time_t rtc_t, estimated_correct_rtc_t; long interval; @@ -989,7 +989,15 @@ RTC_Linux_TimePreInit(void) return; /* Can't open it, and won't be able to later */ } - status = ioctl(fd, RTC_RD_TIME, &rtc_raw); + /* Retry reading the rtc until both read attempts give the same sec value. + This way the race condition is prevented that the RTC has updated itself + during the first read operation. */ + do { + status = ioctl(fd, RTC_RD_TIME, &rtc_raw); + if (status >= 0) { + status = ioctl(fd, RTC_RD_TIME, &rtc_raw_retry); + } + } while (status >= 0 && rtc_raw.tm_sec != rtc_raw_retry.tm_sec); if (status >= 0) { /* Convert to seconds since 1970 */