Ian Kent 1cd346
autofs-5.1.1 - use monotonic clock for alarm thread condition wait
Ian Kent 1cd346
Ian Kent 1cd346
From: Yu Ning <ning.yu@ubuntu.com>
Ian Kent 1cd346
Ian Kent 1cd346
The time returned by gettimeofday() is affected by discontinuous jumps
Ian Kent 1cd346
in the system time, so it causes an issue that autofs may not auto
Ian Kent 1cd346
unmount a mount point if system time is manually changed by the system
Ian Kent 1cd346
administrator.
Ian Kent 1cd346
Ian Kent 1cd346
To fix the issue we need to convert to using a monotonic clock source
Ian Kent 1cd346
instead of the clock source used by gettimeofday().
Ian Kent 1cd346
Ian Kent 1cd346
Convert the alarm_handler() to use a monotonic clock source.
Ian Kent 1cd346
Ian Kent 1cd346
Signed-off-by: Yu Ning <ning.yu@ubuntu.com>
Ian Kent 1cd346
Signed-off-by: Ian Kent <raven@themaw.net>
Ian Kent 1cd346
---
Ian Kent 1cd346
 CHANGELOG   |    1 +
Ian Kent 1cd346
 lib/alarm.c |   28 ++++++++++++++++++++++------
Ian Kent 1cd346
 2 files changed, 23 insertions(+), 6 deletions(-)
Ian Kent 1cd346
Ian Kent 1cd346
diff --git a/CHANGELOG b/CHANGELOG
Ian Kent 1cd346
index 566a6c6..c443f49 100644
Ian Kent 1cd346
--- a/CHANGELOG
Ian Kent 1cd346
+++ b/CHANGELOG
Ian Kent 1cd346
@@ -24,6 +24,7 @@
Ian Kent 1cd346
 - fix error handling of is_mounted().
Ian Kent 1cd346
 - Add a mode option for master map entries.
Ian Kent 1cd346
 - define monotonic clock helper functions.
Ian Kent 1cd346
+- use monotonic clock for alarm thread condition wait.
Ian Kent 1cd346
 
Ian Kent 1cd346
 21/04/2015 autofs-5.1.1
Ian Kent 1cd346
 =======================
Ian Kent 1cd346
diff --git a/lib/alarm.c b/lib/alarm.c
Ian Kent 1cd346
index 0f04ef8..e6a880b 100755
Ian Kent 1cd346
--- a/lib/alarm.c
Ian Kent 1cd346
+++ b/lib/alarm.c
Ian Kent 1cd346
@@ -23,7 +23,7 @@ struct alarm {
Ian Kent 1cd346
 };
Ian Kent 1cd346
 
Ian Kent 1cd346
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Ian Kent 1cd346
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
Ian Kent 1cd346
+static pthread_cond_t cond;
Ian Kent 1cd346
 static LIST_HEAD(alarms);
Ian Kent 1cd346
 
Ian Kent 1cd346
 #define alarm_lock() \
Ian Kent 1cd346
@@ -46,7 +46,7 @@ int alarm_add(struct autofs_point *ap, time_t seconds)
Ian Kent 1cd346
 	struct list_head *head;
Ian Kent 1cd346
 	struct list_head *p;
Ian Kent 1cd346
 	struct alarm *new;
Ian Kent 1cd346
-	time_t now = time(NULL);
Ian Kent 1cd346
+	time_t now = monotonic_time(NULL);
Ian Kent 1cd346
 	time_t next_alarm = 0;
Ian Kent 1cd346
 	unsigned int empty = 1;
Ian Kent 1cd346
 	int status;
Ian Kent 1cd346
@@ -175,17 +175,18 @@ static void *alarm_handler(void *arg)
Ian Kent 1cd346
 
Ian Kent 1cd346
 		first = list_entry(head->next, struct alarm, list);
Ian Kent 1cd346
 
Ian Kent 1cd346
-		now = time(NULL);
Ian Kent 1cd346
+		now = monotonic_time(NULL);
Ian Kent 1cd346
 
Ian Kent 1cd346
 		if (first->time > now) {
Ian Kent 1cd346
-			struct timeval usecs;
Ian Kent 1cd346
+			struct timespec nsecs;
Ian Kent 1cd346
+
Ian Kent 1cd346
 			/* 
Ian Kent 1cd346
 			 * Wait for alarm to trigger or a new alarm 
Ian Kent 1cd346
 			 * to be added.
Ian Kent 1cd346
 			 */
Ian Kent 1cd346
-			gettimeofday(&usecs, NULL);
Ian Kent 1cd346
+			clock_gettime(CLOCK_MONOTONIC, &nsecs);
Ian Kent 1cd346
 			expire.tv_sec = first->time;
Ian Kent 1cd346
-			expire.tv_nsec = usecs.tv_usec * 1000;
Ian Kent 1cd346
+			expire.tv_nsec = nsecs.tv_nsec;
Ian Kent 1cd346
 
Ian Kent 1cd346
 			status = pthread_cond_timedwait(&cond, &mutex, &expire);
Ian Kent 1cd346
 			if (status && status != ETIMEDOUT)
Ian Kent 1cd346
@@ -212,6 +213,7 @@ int alarm_start_handler(void)
Ian Kent 1cd346
 	pthread_t thid;
Ian Kent 1cd346
 	pthread_attr_t attrs;
Ian Kent 1cd346
 	pthread_attr_t *pattrs = &attrs;
Ian Kent 1cd346
+	pthread_condattr_t condattrs;
Ian Kent 1cd346
 	int status;
Ian Kent 1cd346
 
Ian Kent 1cd346
 	status = pthread_attr_init(pattrs);
Ian Kent 1cd346
@@ -224,8 +226,22 @@ int alarm_start_handler(void)
Ian Kent 1cd346
 #endif
Ian Kent 1cd346
 	}
Ian Kent 1cd346
 
Ian Kent 1cd346
+	status = pthread_condattr_init(&condattrs);
Ian Kent 1cd346
+	if (status)
Ian Kent 1cd346
+		fatal(status);
Ian Kent 1cd346
+
Ian Kent 1cd346
+	status = pthread_condattr_setclock(&condattrs, CLOCK_MONOTONIC);
Ian Kent 1cd346
+	if (status)
Ian Kent 1cd346
+		fatal(status);
Ian Kent 1cd346
+
Ian Kent 1cd346
+	status = pthread_cond_init(&cond, &condattrs);
Ian Kent 1cd346
+	if (status)
Ian Kent 1cd346
+		fatal(status);
Ian Kent 1cd346
+
Ian Kent 1cd346
 	status = pthread_create(&thid, pattrs, alarm_handler, NULL);
Ian Kent 1cd346
 
Ian Kent 1cd346
+	pthread_condattr_destroy(&condattrs);
Ian Kent 1cd346
+
Ian Kent 1cd346
 	if (pattrs)
Ian Kent 1cd346
 		pthread_attr_destroy(pattrs);
Ian Kent 1cd346