]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
rtc: more reliable method of reading rtc for initial trim
authorHattink, Tjalling [FINT] <T.Hattink@fugro.nl>
Wed, 28 May 2014 11:54:27 +0000 (13:54 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 2 Jun 2014 14:15:17 +0000 (16:15 +0200)
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.

rtc_linux.c

index 91b0cacc90184e1bd1b56c29b2e3f69ceac76f82..198e3b7c10533abfc87305a7139beb5f059dc629 100644 (file)
@@ -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 */