]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tree-wide: don't assume CLOCK_BOOTIME is generally available
authorLennart Poettering <lennart@poettering.net>
Wed, 20 Apr 2016 16:12:57 +0000 (18:12 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Apr 2016 14:06:20 +0000 (16:06 +0200)
Before we invoke now(CLOCK_BOOTTIME), let's make sure we actually have that
clock, since now() will otherwise hit an assert.

Specifically, let's refuse CLOCK_BOOTTIME early in sd-event if the kernel
doesn't actually support it.

This is a follow-up for #3037, and specifically:

https://github.com/systemd/systemd/pull/3037#issuecomment-210199167

src/basic/time-util.c
src/basic/time-util.h
src/core/timer.c
src/libsystemd/sd-event/sd-event.c
src/libsystemd/sd-event/test-event.c

index 7ca764abeb0bda412a9c27b05c0fdbad98d4426a..edd9179cb8259042a6ac8d4762aeb4559467b193 100644 (file)
@@ -1080,22 +1080,31 @@ bool timezone_is_valid(const char *name) {
         return true;
 }
 
-clockid_t clock_boottime_or_monotonic(void) {
-        static clockid_t clock = -1;
-        int fd;
-
-        if (clock != -1)
-                return clock;
-
-        fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
-        if (fd < 0)
-                clock = CLOCK_MONOTONIC;
-        else {
-                safe_close(fd);
-                clock = CLOCK_BOOTTIME;
+bool clock_boottime_supported(void) {
+        static int supported = -1;
+
+        /* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */
+
+        if (supported < 0) {
+                int fd;
+
+                fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+                if (fd < 0)
+                        supported = false;
+                else {
+                        safe_close(fd);
+                        supported = true;
+                }
         }
 
-        return clock;
+        return supported;
+}
+
+clockid_t clock_boottime_or_monotonic(void) {
+        if (clock_boottime_supported())
+                return CLOCK_BOOTTIME;
+        else
+                return CLOCK_MONOTONIC;
 }
 
 int get_timezone(char **tz) {
index 77e3cd08d4307f6a840ba4884793afc95906a7e9..a5e3f567ec534fad1de41cd55e642ccacd423722 100644 (file)
@@ -112,6 +112,7 @@ bool ntp_synced(void);
 int get_timezones(char ***l);
 bool timezone_is_valid(const char *name);
 
+bool clock_boottime_supported(void);
 clockid_t clock_boottime_or_monotonic(void);
 
 #define xstrftime(buf, fmt, tm) \
index b286b714faca89a2693755beec13d2925994a497..f8f5f4b2e48d00192c15398684df5a2b85e399cc 100644 (file)
@@ -373,7 +373,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
          * rather than the monotonic clock. */
 
         ts_realtime = now(CLOCK_REALTIME);
-        ts_monotonic = now(t->wake_system ? CLOCK_BOOTTIME : CLOCK_MONOTONIC);
+        ts_monotonic = now(t->wake_system ? clock_boottime_or_monotonic() : CLOCK_MONOTONIC);
         t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
 
         LIST_FOREACH(value, v, t->values) {
index 79b98c293c6ac14999595df961f368c550960ebc..7ba6527f63164dbdfafcf81c5e61c865eb73db90 100644 (file)
@@ -1072,6 +1072,10 @@ _public_ int sd_event_add_time(
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
+        if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) &&
+            !clock_boottime_supported())
+                return -EOPNOTSUPP;
+
         if (!callback)
                 callback = time_exit_callback;
 
@@ -2527,7 +2531,8 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
         }
 
         dual_timestamp_get(&e->timestamp);
-        e->timestamp_boottime = now(clock_boottime_or_monotonic());
+        if (clock_boottime_supported())
+                e->timestamp_boottime = now(CLOCK_BOOTTIME);
 
         for (i = 0; i < m; i++) {
 
@@ -2761,6 +2766,9 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
                              CLOCK_BOOTTIME,
                              CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP);
 
+        if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported())
+                return -EOPNOTSUPP;
+
         if (!dual_timestamp_is_set(&e->timestamp)) {
                 /* Implicitly fall back to now() if we never ran
                  * before and thus have no cached time. */
index fd31588b8f2ba1d47144ba07ef8453b63ad835b7..289114490ccf6d1765b70c7cdfbdb0e70f8f05de 100644 (file)
@@ -270,8 +270,10 @@ static void test_sd_event_now(void) {
         assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0);
         assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0);
         assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0);
-        assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0);
-        assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0);
+        if (clock_boottime_supported()) {
+                assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0);
+                assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0);
+        }
         assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
         assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
 
@@ -280,8 +282,10 @@ static void test_sd_event_now(void) {
         assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0);
         assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0);
         assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0);
-        assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
-        assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0);
+        if (clock_boottime_supported()) {
+                assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
+                assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0);
+        }
         assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
         assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
 }