mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
tree-wide: don't assume CLOCK_BOOTIME is generally available
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
This commit is contained in:
parent
f53d86c929
commit
3411372e35
@ -1080,22 +1080,31 @@ bool timezone_is_valid(const char *name) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
clockid_t clock_boottime_or_monotonic(void) {
|
bool clock_boottime_supported(void) {
|
||||||
static clockid_t clock = -1;
|
static int supported = -1;
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (clock != -1)
|
/* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */
|
||||||
return clock;
|
|
||||||
|
|
||||||
fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
|
if (supported < 0) {
|
||||||
if (fd < 0)
|
int fd;
|
||||||
clock = CLOCK_MONOTONIC;
|
|
||||||
else {
|
fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
|
||||||
safe_close(fd);
|
if (fd < 0)
|
||||||
clock = CLOCK_BOOTTIME;
|
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) {
|
int get_timezone(char **tz) {
|
||||||
|
@ -112,6 +112,7 @@ bool ntp_synced(void);
|
|||||||
int get_timezones(char ***l);
|
int get_timezones(char ***l);
|
||||||
bool timezone_is_valid(const char *name);
|
bool timezone_is_valid(const char *name);
|
||||||
|
|
||||||
|
bool clock_boottime_supported(void);
|
||||||
clockid_t clock_boottime_or_monotonic(void);
|
clockid_t clock_boottime_or_monotonic(void);
|
||||||
|
|
||||||
#define xstrftime(buf, fmt, tm) \
|
#define xstrftime(buf, fmt, tm) \
|
||||||
|
@ -373,7 +373,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
|
|||||||
* rather than the monotonic clock. */
|
* rather than the monotonic clock. */
|
||||||
|
|
||||||
ts_realtime = now(CLOCK_REALTIME);
|
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;
|
t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
|
||||||
|
|
||||||
LIST_FOREACH(value, v, t->values) {
|
LIST_FOREACH(value, v, t->values) {
|
||||||
|
@ -1072,6 +1072,10 @@ _public_ int sd_event_add_time(
|
|||||||
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
|
||||||
assert_return(!event_pid_changed(e), -ECHILD);
|
assert_return(!event_pid_changed(e), -ECHILD);
|
||||||
|
|
||||||
|
if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) &&
|
||||||
|
!clock_boottime_supported())
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (!callback)
|
if (!callback)
|
||||||
callback = time_exit_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);
|
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++) {
|
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,
|
||||||
CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP);
|
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)) {
|
if (!dual_timestamp_is_set(&e->timestamp)) {
|
||||||
/* Implicitly fall back to now() if we never ran
|
/* Implicitly fall back to now() if we never ran
|
||||||
* before and thus have no cached time. */
|
* before and thus have no cached time. */
|
||||||
|
@ -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_MONOTONIC, &event_now) > 0);
|
||||||
assert_se(sd_event_now(e, CLOCK_REALTIME, &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_REALTIME_ALARM, &event_now) > 0);
|
||||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0);
|
if (clock_boottime_supported()) {
|
||||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME_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);
|
||||||
|
}
|
||||||
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
|
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
|
||||||
assert_se(sd_event_now(e, 900 /* arbitrary big number */, &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_MONOTONIC, &event_now) == 0);
|
||||||
assert_se(sd_event_now(e, CLOCK_REALTIME, &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_REALTIME_ALARM, &event_now) == 0);
|
||||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0);
|
if (clock_boottime_supported()) {
|
||||||
assert_se(sd_event_now(e, CLOCK_BOOTTIME_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);
|
||||||
|
}
|
||||||
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
|
assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP);
|
||||||
assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
|
assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user