From 2ed9853bcc6a2e75749dd8a8153cdfb9efd8b236 Mon Sep 17 00:00:00 2001 From: "Hattink, Tjalling [FINT]" Date: Wed, 28 May 2014 13:54:27 +0200 Subject: [PATCH] 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. --- rtc_linux.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/rtc_linux.c b/rtc_linux.c index 91b0cac..198e3b7 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 */