Skip to content

Commit fee04d7

Browse files
iplayinsunpoettering
authored andcommitted
core: don't drop timer expired but not yet processed when system date is changed
There is difference between time set by the user and real elapsed time because of accuracy feature. If you change the system date(or time) between these times, the timer drops. You can easily reproduce it with the following command. ----------------------------------------------------------- $ systemd-run --on-active=3s ls; sleep 3; date -s "`date`" ----------------------------------------------------------- In the following command, the problem is rarely reproduced. But it exists. --------------------------------------------------------------------------------------------- $ systemd-run --on-active=3s --timer-property=AccuracySec=1us ls ; sleep 1; date -s "`date`" --------------------------------------------------------------------------------------------- Note : Global AccuracySec value. ---------------------------------------------------------------------- $ cat /etc/systemd/system.conf DefaultTimerAccuracySec=1min ----------------------------------------------------------------------
1 parent c1b785b commit fee04d7

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

src/core/timer.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ static void timer_set_state(Timer *t, TimerState state) {
263263
unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
264264
}
265265

266-
static void timer_enter_waiting(Timer *t, bool initial);
266+
static void timer_enter_waiting(Timer *t, bool initial, bool time_change);
267267

268268
static int timer_coldplug(Unit *u) {
269269
Timer *t = TIMER(u);
@@ -275,7 +275,7 @@ static int timer_coldplug(Unit *u) {
275275
return 0;
276276

277277
if (t->deserialized_state == TIMER_WAITING)
278-
timer_enter_waiting(t, false);
278+
timer_enter_waiting(t, false, false);
279279
else
280280
timer_set_state(t, t->deserialized_state);
281281

@@ -333,7 +333,7 @@ static void add_random(Timer *t, usec_t *v) {
333333
log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
334334
}
335335

336-
static void timer_enter_waiting(Timer *t, bool initial) {
336+
static void timer_enter_waiting(Timer *t, bool initial, bool time_change) {
337337
bool found_monotonic = false, found_realtime = false;
338338
bool leave_around = false;
339339
triple_timestamp ts;
@@ -443,7 +443,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
443443

444444
v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value);
445445

446-
if (!initial &&
446+
if (!initial && !time_change &&
447447
v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) &&
448448
IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
449449
/* This is a one time trigger, disable it now */
@@ -641,7 +641,7 @@ static int timer_start(Unit *u) {
641641
}
642642

643643
t->result = TIMER_SUCCESS;
644-
timer_enter_waiting(t, true);
644+
timer_enter_waiting(t, true, false);
645645
return 1;
646646
}
647647

@@ -756,14 +756,14 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
756756
case TIMER_ELAPSED:
757757

758758
/* Recalculate sleep time */
759-
timer_enter_waiting(t, false);
759+
timer_enter_waiting(t, false, false);
760760
break;
761761

762762
case TIMER_RUNNING:
763763

764764
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
765765
log_unit_debug(UNIT(t), "Got notified about unit deactivation.");
766-
timer_enter_waiting(t, false);
766+
timer_enter_waiting(t, false, false);
767767
}
768768
break;
769769

@@ -805,7 +805,7 @@ static void timer_time_change(Unit *u) {
805805
t->last_trigger.realtime = ts;
806806

807807
log_unit_debug(u, "Time change, recalculating next elapse.");
808-
timer_enter_waiting(t, false);
808+
timer_enter_waiting(t, false, true);
809809
}
810810

811811
static void timer_timezone_change(Unit *u) {
@@ -817,7 +817,7 @@ static void timer_timezone_change(Unit *u) {
817817
return;
818818

819819
log_unit_debug(u, "Timezone change, recalculating next elapse.");
820-
timer_enter_waiting(t, false);
820+
timer_enter_waiting(t, false, false);
821821
}
822822

823823
static const char* const timer_base_table[_TIMER_BASE_MAX] = {

0 commit comments

Comments
 (0)