1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "alloc-util.h"
10 #include "bus-error.h"
11 #include "calendarspec.h"
12 #include "dbus-timer.h"
13 #include "dbus-unit.h"
16 #include "random-util.h"
17 #include "serialize.h"
18 #include "siphash24.h"
20 #include "string-table.h"
21 #include "string-util.h"
25 #include "user-util.h"
28 static const UnitActiveState state_translation_table
[_TIMER_STATE_MAX
] = {
29 [TIMER_DEAD
] = UNIT_INACTIVE
,
30 [TIMER_WAITING
] = UNIT_ACTIVE
,
31 [TIMER_RUNNING
] = UNIT_ACTIVE
,
32 [TIMER_ELAPSED
] = UNIT_ACTIVE
,
33 [TIMER_FAILED
] = UNIT_FAILED
,
36 static int timer_dispatch(sd_event_source
*s
, uint64_t usec
, void *userdata
);
38 static void timer_init(Unit
*u
) {
39 Timer
*t
= ASSERT_PTR(TIMER(u
));
41 assert(u
->load_state
== UNIT_STUB
);
43 t
->next_elapse_monotonic_or_boottime
= USEC_INFINITY
;
44 t
->next_elapse_realtime
= USEC_INFINITY
;
45 t
->accuracy_usec
= u
->manager
->defaults
.timer_accuracy_usec
;
46 t
->remain_after_elapse
= true;
49 void timer_free_values(Timer
*t
) {
54 while ((v
= LIST_POP(value
, t
->values
))) {
55 calendar_spec_free(v
->calendar_spec
);
60 static void timer_done(Unit
*u
) {
61 Timer
*t
= ASSERT_PTR(TIMER(u
));
65 t
->monotonic_event_source
= sd_event_source_disable_unref(t
->monotonic_event_source
);
66 t
->realtime_event_source
= sd_event_source_disable_unref(t
->realtime_event_source
);
68 t
->stamp_path
= mfree(t
->stamp_path
);
71 static int timer_verify(Timer
*t
) {
73 assert(UNIT(t
)->load_state
== UNIT_LOADED
);
75 if (!t
->values
&& !t
->on_clock_change
&& !t
->on_timezone_change
)
76 return log_unit_error_errno(UNIT(t
), SYNTHETIC_ERRNO(ENOEXEC
), "Timer unit lacks value setting. Refusing.");
81 static int timer_add_default_dependencies(Timer
*t
) {
86 if (!UNIT(t
)->default_dependencies
)
89 r
= unit_add_dependency_by_name(UNIT(t
), UNIT_BEFORE
, SPECIAL_TIMERS_TARGET
, true, UNIT_DEPENDENCY_DEFAULT
);
93 if (MANAGER_IS_SYSTEM(UNIT(t
)->manager
)) {
94 r
= unit_add_two_dependencies_by_name(UNIT(t
), UNIT_AFTER
, UNIT_REQUIRES
, SPECIAL_SYSINIT_TARGET
, true, UNIT_DEPENDENCY_DEFAULT
);
98 LIST_FOREACH(value
, v
, t
->values
) {
99 if (v
->base
!= TIMER_CALENDAR
)
102 FOREACH_STRING(target
, SPECIAL_TIME_SYNC_TARGET
, SPECIAL_TIME_SET_TARGET
) {
103 r
= unit_add_dependency_by_name(UNIT(t
), UNIT_AFTER
, target
, true, UNIT_DEPENDENCY_DEFAULT
);
112 return unit_add_two_dependencies_by_name(UNIT(t
), UNIT_BEFORE
, UNIT_CONFLICTS
, SPECIAL_SHUTDOWN_TARGET
, true, UNIT_DEPENDENCY_DEFAULT
);
115 static int timer_add_trigger_dependencies(Timer
*t
) {
121 if (UNIT_TRIGGER(UNIT(t
)))
124 r
= unit_load_related_unit(UNIT(t
), ".service", &x
);
128 return unit_add_two_dependencies(UNIT(t
), UNIT_BEFORE
, UNIT_TRIGGERS
, x
, true, UNIT_DEPENDENCY_IMPLICIT
);
131 static int timer_setup_persistent(Timer
*t
) {
132 _cleanup_free_
char *stamp_path
= NULL
;
140 if (MANAGER_IS_SYSTEM(UNIT(t
)->manager
)) {
142 r
= unit_add_mounts_for(UNIT(t
), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE
, UNIT_MOUNT_REQUIRES
);
146 stamp_path
= strjoin("/var/lib/systemd/timers/stamp-", UNIT(t
)->id
);
150 e
= getenv("XDG_DATA_HOME");
152 stamp_path
= strjoin(e
, "/systemd/timers/stamp-", UNIT(t
)->id
);
155 _cleanup_free_
char *h
= NULL
;
157 r
= get_home_dir(&h
);
159 return log_unit_error_errno(UNIT(t
), r
, "Failed to determine home directory: %m");
161 stamp_path
= strjoin(h
, "/.local/share/systemd/timers/stamp-", UNIT(t
)->id
);
168 return free_and_replace(t
->stamp_path
, stamp_path
);
171 static uint64_t timer_get_fixed_delay_hash(Timer
*t
) {
172 static const uint8_t hash_key
[] = {
173 0x51, 0x0a, 0xdb, 0x76, 0x29, 0x51, 0x42, 0xc2,
174 0x80, 0x35, 0xea, 0xe6, 0x8e, 0x3a, 0x37, 0xbd
177 struct siphash state
;
178 sd_id128_t machine_id
;
185 r
= sd_id128_get_machine(&machine_id
);
187 log_unit_debug_errno(UNIT(t
), r
,
188 "Failed to get machine ID for the fixed delay calculation, proceeding with 0: %m");
189 machine_id
= SD_ID128_NULL
;
192 siphash24_init(&state
, hash_key
);
193 siphash24_compress_typesafe(machine_id
, &state
);
194 siphash24_compress_boolean(MANAGER_IS_SYSTEM(UNIT(t
)->manager
), &state
);
195 siphash24_compress_typesafe(uid
, &state
);
196 siphash24_compress_string(UNIT(t
)->id
, &state
);
198 return siphash24_finalize(&state
);
201 static int timer_load(Unit
*u
) {
202 Timer
*t
= ASSERT_PTR(TIMER(u
));
205 assert(u
->load_state
== UNIT_STUB
);
207 r
= unit_load_fragment_and_dropin(u
, true);
211 if (u
->load_state
!= UNIT_LOADED
)
214 /* This is a new unit? Then let's add in some extras */
215 r
= timer_add_trigger_dependencies(t
);
219 r
= timer_setup_persistent(t
);
223 r
= timer_add_default_dependencies(t
);
227 return timer_verify(t
);
230 static void timer_dump(Unit
*u
, FILE *f
, const char *prefix
) {
231 Timer
*t
= ASSERT_PTR(TIMER(u
));
237 trigger
= UNIT_TRIGGER(u
);
240 "%sTimer State: %s\n"
246 "%sRemainAfterElapse: %s\n"
247 "%sFixedRandomDelay: %s\n"
248 "%sOnClockChange: %s\n"
249 "%sOnTimeZoneChange: %s\n"
250 "%sDeferReactivation: %s\n",
251 prefix
, timer_state_to_string(t
->state
),
252 prefix
, timer_result_to_string(t
->result
),
253 prefix
, trigger
? trigger
->id
: "n/a",
254 prefix
, yes_no(t
->persistent
),
255 prefix
, yes_no(t
->wake_system
),
256 prefix
, FORMAT_TIMESPAN(t
->accuracy_usec
, 1),
257 prefix
, yes_no(t
->remain_after_elapse
),
258 prefix
, yes_no(t
->fixed_random_delay
),
259 prefix
, yes_no(t
->on_clock_change
),
260 prefix
, yes_no(t
->on_timezone_change
),
261 prefix
, yes_no(t
->defer_reactivation
));
263 LIST_FOREACH(value
, v
, t
->values
)
264 if (v
->base
== TIMER_CALENDAR
) {
265 _cleanup_free_
char *p
= NULL
;
267 (void) calendar_spec_to_string(v
->calendar_spec
, &p
);
272 timer_base_to_string(v
->base
),
278 timer_base_to_string(v
->base
),
279 FORMAT_TIMESPAN(v
->value
, 0));
282 static void timer_set_state(Timer
*t
, TimerState state
) {
283 TimerState old_state
;
287 if (t
->state
!= state
)
288 bus_unit_send_pending_change_signal(UNIT(t
), false);
290 old_state
= t
->state
;
293 if (state
!= TIMER_WAITING
) {
294 t
->monotonic_event_source
= sd_event_source_disable_unref(t
->monotonic_event_source
);
295 t
->realtime_event_source
= sd_event_source_disable_unref(t
->realtime_event_source
);
296 t
->next_elapse_monotonic_or_boottime
= USEC_INFINITY
;
297 t
->next_elapse_realtime
= USEC_INFINITY
;
300 if (state
!= old_state
)
301 log_unit_debug(UNIT(t
), "Changed %s -> %s", timer_state_to_string(old_state
), timer_state_to_string(state
));
303 unit_notify(UNIT(t
), state_translation_table
[old_state
], state_translation_table
[state
], /* reload_success = */ true);
306 static void timer_enter_waiting(Timer
*t
, bool time_change
);
308 static int timer_coldplug(Unit
*u
) {
309 Timer
*t
= ASSERT_PTR(TIMER(u
));
311 assert(t
->state
== TIMER_DEAD
);
313 if (t
->deserialized_state
== t
->state
)
316 if (t
->deserialized_state
== TIMER_WAITING
)
317 timer_enter_waiting(t
, false);
319 timer_set_state(t
, t
->deserialized_state
);
324 static void timer_enter_dead(Timer
*t
, TimerResult f
) {
327 if (t
->result
== TIMER_SUCCESS
)
330 unit_log_result(UNIT(t
), t
->result
== TIMER_SUCCESS
, timer_result_to_string(t
->result
));
331 timer_set_state(t
, t
->result
!= TIMER_SUCCESS
? TIMER_FAILED
: TIMER_DEAD
);
334 static void timer_enter_elapsed(Timer
*t
, bool leave_around
) {
337 /* If a unit is marked with RemainAfterElapse=yes we leave it
338 * around even after it elapsed once, so that starting it
339 * later again does not necessarily mean immediate
340 * retriggering. We unconditionally leave units with
341 * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around,
342 * since they might be restarted automatically at any time
345 if (t
->remain_after_elapse
|| leave_around
)
346 timer_set_state(t
, TIMER_ELAPSED
);
348 timer_enter_dead(t
, TIMER_SUCCESS
);
351 static void add_random_delay(Timer
*t
, usec_t
*v
) {
357 if (t
->random_delay_usec
== 0)
359 if (*v
== USEC_INFINITY
)
362 add
= (t
->fixed_random_delay
? timer_get_fixed_delay_hash(t
) : random_u64()) % t
->random_delay_usec
;
364 if (*v
+ add
< *v
) /* overflow */
365 *v
= (usec_t
) -2; /* Highest possible value, that is not USEC_INFINITY */
369 log_unit_debug(UNIT(t
), "Adding %s random time.", FORMAT_TIMESPAN(add
, 0));
372 static void timer_enter_waiting(Timer
*t
, bool time_change
) {
373 bool found_monotonic
= false, found_realtime
= false;
374 bool leave_around
= false;
381 trigger
= UNIT_TRIGGER(UNIT(t
));
383 log_unit_error(UNIT(t
), "Unit to trigger vanished.");
387 triple_timestamp_now(&ts
);
388 t
->next_elapse_monotonic_or_boottime
= t
->next_elapse_realtime
= 0;
390 LIST_FOREACH(value
, v
, t
->values
) {
394 if (v
->base
== TIMER_CALENDAR
) {
395 usec_t b
, rebased
, random_offset
= 0;
397 if (t
->random_offset_usec
!= 0)
398 random_offset
= timer_get_fixed_delay_hash(t
) % t
->random_offset_usec
;
400 /* If DeferReactivation= is enabled, schedule the job based on the last time
401 * the trigger unit entered inactivity. Otherwise, if we know the last time
402 * this was triggered, schedule the job based relative to that. If we don't,
403 * just start from the activation time or realtime.
405 * Unless we have a real last-trigger time, we subtract the random_offset because
406 * any event that elapsed within the last random_offset has actually been delayed
407 * and thus hasn't truly elapsed yet. */
409 if (t
->defer_reactivation
&&
410 dual_timestamp_is_set(&trigger
->inactive_enter_timestamp
)) {
411 if (dual_timestamp_is_set(&t
->last_trigger
))
412 b
= MAX(trigger
->inactive_enter_timestamp
.realtime
,
413 t
->last_trigger
.realtime
);
415 b
= trigger
->inactive_enter_timestamp
.realtime
;
416 } else if (dual_timestamp_is_set(&t
->last_trigger
))
417 b
= t
->last_trigger
.realtime
;
418 else if (dual_timestamp_is_set(&UNIT(t
)->inactive_exit_timestamp
))
419 b
= UNIT(t
)->inactive_exit_timestamp
.realtime
- random_offset
;
421 b
= ts
.realtime
- random_offset
;
423 r
= calendar_spec_next_usec(v
->calendar_spec
, b
, &v
->next_elapse
);
427 v
->next_elapse
+= random_offset
;
429 /* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
430 * time has already passed, set the time when systemd first started as the scheduled
431 * time. Note that we base this on the monotonic timestamp of the boot, not the
432 * realtime one, since the wallclock might have been off during boot. */
433 rebased
= map_clock_usec(UNIT(t
)->manager
->timestamps
[MANAGER_TIMESTAMP_USERSPACE
].monotonic
,
434 CLOCK_MONOTONIC
, CLOCK_REALTIME
);
435 if (v
->next_elapse
< rebased
)
436 v
->next_elapse
= rebased
;
439 t
->next_elapse_realtime
= v
->next_elapse
;
441 t
->next_elapse_realtime
= MIN(t
->next_elapse_realtime
, v
->next_elapse
);
443 found_realtime
= true;
451 if (state_translation_table
[t
->state
] == UNIT_ACTIVE
)
452 base
= UNIT(t
)->inactive_exit_timestamp
.monotonic
;
458 if (detect_container() <= 0) {
459 /* CLOCK_MONOTONIC equals the uptime on Linux */
463 /* In a container we don't want to include the time the host
464 * was already up when the container started, so count from
465 * our own startup. */
468 base
= UNIT(t
)->manager
->timestamps
[MANAGER_TIMESTAMP_USERSPACE
].monotonic
;
471 case TIMER_UNIT_ACTIVE
:
473 base
= MAX(trigger
->inactive_exit_timestamp
.monotonic
, t
->last_trigger
.monotonic
);
478 case TIMER_UNIT_INACTIVE
:
480 base
= MAX(trigger
->inactive_enter_timestamp
.monotonic
, t
->last_trigger
.monotonic
);
486 assert_not_reached();
490 v
->next_elapse
= usec_add(usec_shift_clock(base
, CLOCK_MONOTONIC
, TIMER_MONOTONIC_CLOCK(t
)), v
->value
);
492 if (dual_timestamp_is_set(&t
->last_trigger
) &&
494 v
->next_elapse
< triple_timestamp_by_clock(&ts
, TIMER_MONOTONIC_CLOCK(t
)) &&
495 IN_SET(v
->base
, TIMER_ACTIVE
, TIMER_BOOT
, TIMER_STARTUP
)) {
496 /* This is a one time trigger, disable it now */
501 if (!found_monotonic
)
502 t
->next_elapse_monotonic_or_boottime
= v
->next_elapse
;
504 t
->next_elapse_monotonic_or_boottime
= MIN(t
->next_elapse_monotonic_or_boottime
, v
->next_elapse
);
506 found_monotonic
= true;
510 if (!found_monotonic
&& !found_realtime
&& !t
->on_timezone_change
&& !t
->on_clock_change
) {
511 log_unit_debug(UNIT(t
), "Timer is elapsed.");
512 timer_enter_elapsed(t
, leave_around
);
516 if (found_monotonic
) {
519 add_random_delay(t
, &t
->next_elapse_monotonic_or_boottime
);
521 left
= usec_sub_unsigned(t
->next_elapse_monotonic_or_boottime
, triple_timestamp_by_clock(&ts
, TIMER_MONOTONIC_CLOCK(t
)));
522 log_unit_debug(UNIT(t
), "Monotonic timer elapses in %s.", FORMAT_TIMESPAN(left
, 0));
524 if (t
->monotonic_event_source
) {
525 r
= sd_event_source_set_time(t
->monotonic_event_source
, t
->next_elapse_monotonic_or_boottime
);
527 log_unit_warning_errno(UNIT(t
), r
, "Failed to reschedule monotonic event source: %m");
531 r
= sd_event_source_set_enabled(t
->monotonic_event_source
, SD_EVENT_ONESHOT
);
533 log_unit_warning_errno(UNIT(t
), r
, "Failed to enable monotonic event source: %m");
537 r
= sd_event_add_time(
538 UNIT(t
)->manager
->event
,
539 &t
->monotonic_event_source
,
540 t
->wake_system
? CLOCK_BOOTTIME_ALARM
: CLOCK_MONOTONIC
,
541 t
->next_elapse_monotonic_or_boottime
, t
->accuracy_usec
,
544 log_unit_warning_errno(UNIT(t
), r
, "Failed to add monotonic event source: %m");
548 (void) sd_event_source_set_description(t
->monotonic_event_source
, "timer-monotonic");
552 r
= sd_event_source_set_enabled(t
->monotonic_event_source
, SD_EVENT_OFF
);
554 log_unit_warning_errno(UNIT(t
), r
, "Failed to disable monotonic event source: %m");
559 if (found_realtime
) {
560 add_random_delay(t
, &t
->next_elapse_realtime
);
562 log_unit_debug(UNIT(t
), "Realtime timer elapses at %s.", FORMAT_TIMESTAMP(t
->next_elapse_realtime
));
564 if (t
->realtime_event_source
) {
565 r
= sd_event_source_set_time(t
->realtime_event_source
, t
->next_elapse_realtime
);
567 log_unit_warning_errno(UNIT(t
), r
, "Failed to reschedule realtime event source: %m");
571 r
= sd_event_source_set_enabled(t
->realtime_event_source
, SD_EVENT_ONESHOT
);
573 log_unit_warning_errno(UNIT(t
), r
, "Failed to enable realtime event source: %m");
577 r
= sd_event_add_time(
578 UNIT(t
)->manager
->event
,
579 &t
->realtime_event_source
,
580 t
->wake_system
? CLOCK_REALTIME_ALARM
: CLOCK_REALTIME
,
581 t
->next_elapse_realtime
, t
->accuracy_usec
,
584 log_unit_warning_errno(UNIT(t
), r
, "Failed to add realtime event source: %m");
588 (void) sd_event_source_set_description(t
->realtime_event_source
, "timer-realtime");
591 } else if (t
->realtime_event_source
) {
593 r
= sd_event_source_set_enabled(t
->realtime_event_source
, SD_EVENT_OFF
);
595 log_unit_warning_errno(UNIT(t
), r
, "Failed to disable realtime event source: %m");
600 timer_set_state(t
, TIMER_WAITING
);
604 timer_enter_dead(t
, TIMER_FAILURE_RESOURCES
);
607 static void timer_enter_running(Timer
*t
) {
608 _cleanup_(activation_details_unrefp
) ActivationDetails
*details
= NULL
;
609 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
616 /* Don't start job if we are supposed to go down */
617 if (unit_stop_pending(UNIT(t
)))
620 trigger
= UNIT_TRIGGER(UNIT(t
));
622 log_unit_error(UNIT(t
), "Unit to trigger vanished.");
626 details
= activation_details_new(UNIT(t
));
632 r
= manager_add_job(UNIT(t
)->manager
, JOB_START
, trigger
, JOB_REPLACE
, &error
, &job
);
634 log_unit_warning(UNIT(t
), "Failed to queue unit startup job: %s", bus_error_message(&error
, r
));
638 dual_timestamp_now(&t
->last_trigger
);
639 ACTIVATION_DETAILS_TIMER(details
)->last_trigger
= t
->last_trigger
;
641 job_set_activation_details(job
, details
);
644 touch_file(t
->stamp_path
, true, t
->last_trigger
.realtime
, UID_INVALID
, GID_INVALID
, MODE_INVALID
);
646 timer_set_state(t
, TIMER_RUNNING
);
650 timer_enter_dead(t
, TIMER_FAILURE_RESOURCES
);
653 static int timer_start(Unit
*u
) {
654 Timer
*t
= ASSERT_PTR(TIMER(u
));
657 assert(IN_SET(t
->state
, TIMER_DEAD
, TIMER_FAILED
));
659 r
= unit_test_trigger_loaded(u
);
663 r
= unit_acquire_invocation_id(u
);
667 t
->last_trigger
= DUAL_TIMESTAMP_NULL
;
669 /* Reenable all timers that depend on unit activation time */
670 LIST_FOREACH(value
, v
, t
->values
)
671 if (v
->base
== TIMER_ACTIVE
)
677 if (stat(t
->stamp_path
, &st
) >= 0) {
680 /* Load the file timestamp, but only if it is actually in the past. If it is in the future,
681 * something is wrong with the system clock. */
683 ft
= timespec_load(&st
.st_mtim
);
684 if (ft
< now(CLOCK_REALTIME
))
685 t
->last_trigger
.realtime
= ft
;
687 log_unit_warning(u
, "Not using persistent file timestamp %s as it is in the future.",
688 FORMAT_TIMESTAMP(ft
));
690 } else if (errno
== ENOENT
)
691 /* The timer has never run before, make sure a stamp file exists. */
692 (void) touch_file(t
->stamp_path
, true, USEC_INFINITY
, UID_INVALID
, GID_INVALID
, MODE_INVALID
);
695 t
->result
= TIMER_SUCCESS
;
696 timer_enter_waiting(t
, false);
700 static int timer_stop(Unit
*u
) {
701 Timer
*t
= ASSERT_PTR(TIMER(u
));
703 assert(IN_SET(t
->state
, TIMER_WAITING
, TIMER_RUNNING
, TIMER_ELAPSED
));
705 timer_enter_dead(t
, TIMER_SUCCESS
);
709 static int timer_serialize(Unit
*u
, FILE *f
, FDSet
*fds
) {
710 Timer
*t
= ASSERT_PTR(TIMER(u
));
715 (void) serialize_item(f
, "state", timer_state_to_string(t
->state
));
716 (void) serialize_item(f
, "result", timer_result_to_string(t
->result
));
718 if (dual_timestamp_is_set(&t
->last_trigger
))
719 (void) serialize_usec(f
, "last-trigger-realtime", t
->last_trigger
.realtime
);
721 if (t
->last_trigger
.monotonic
> 0)
722 (void) serialize_usec(f
, "last-trigger-monotonic", t
->last_trigger
.monotonic
);
727 static int timer_deserialize_item(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
728 Timer
*t
= ASSERT_PTR(TIMER(u
));
734 if (streq(key
, "state")) {
737 state
= timer_state_from_string(value
);
739 log_unit_debug(u
, "Failed to parse state value: %s", value
);
741 t
->deserialized_state
= state
;
743 } else if (streq(key
, "result")) {
746 f
= timer_result_from_string(value
);
748 log_unit_debug(u
, "Failed to parse result value: %s", value
);
749 else if (f
!= TIMER_SUCCESS
)
752 } else if (streq(key
, "last-trigger-realtime"))
753 (void) deserialize_usec(value
, &t
->last_trigger
.realtime
);
754 else if (streq(key
, "last-trigger-monotonic"))
755 (void) deserialize_usec(value
, &t
->last_trigger
.monotonic
);
757 log_unit_debug(u
, "Unknown serialization key: %s", key
);
762 static UnitActiveState
timer_active_state(Unit
*u
) {
763 Timer
*t
= ASSERT_PTR(TIMER(u
));
765 return state_translation_table
[t
->state
];
768 static const char *timer_sub_state_to_string(Unit
*u
) {
769 Timer
*t
= ASSERT_PTR(TIMER(u
));
771 return timer_state_to_string(t
->state
);
774 static int timer_dispatch(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
775 Timer
*t
= ASSERT_PTR(TIMER(userdata
));
777 if (t
->state
!= TIMER_WAITING
)
780 log_unit_debug(UNIT(t
), "Timer elapsed.");
781 timer_enter_running(t
);
785 static void timer_trigger_notify(Unit
*u
, Unit
*other
) {
786 Timer
*t
= ASSERT_PTR(TIMER(u
));
790 /* Filter out invocations with bogus state */
791 assert(UNIT_IS_LOAD_COMPLETE(other
->load_state
));
793 /* Reenable all timers that depend on unit state */
794 LIST_FOREACH(value
, v
, t
->values
)
795 if (IN_SET(v
->base
, TIMER_UNIT_ACTIVE
, TIMER_UNIT_INACTIVE
))
803 /* Recalculate sleep time */
804 timer_enter_waiting(t
, false);
809 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other
))) {
810 log_unit_debug(UNIT(t
), "Got notified about unit deactivation.");
811 timer_enter_waiting(t
, false);
820 assert_not_reached();
824 static void timer_reset_failed(Unit
*u
) {
825 Timer
*t
= ASSERT_PTR(TIMER(u
));
827 if (t
->state
== TIMER_FAILED
)
828 timer_set_state(t
, TIMER_DEAD
);
830 t
->result
= TIMER_SUCCESS
;
833 static void timer_time_change(Unit
*u
) {
834 Timer
*t
= ASSERT_PTR(TIMER(u
));
837 if (t
->state
!= TIMER_WAITING
)
840 /* If we appear to have triggered in the future, the system clock must
841 * have been set backwards. So let's rewind our own clock and allow
842 * the future triggers to happen again :). Exactly the same as when
843 * you start a timer unit with Persistent=yes. */
844 ts
= now(CLOCK_REALTIME
);
845 if (t
->last_trigger
.realtime
> ts
)
846 t
->last_trigger
.realtime
= ts
;
848 if (t
->on_clock_change
) {
849 log_unit_debug(u
, "Time change, triggering activation.");
850 timer_enter_running(t
);
852 log_unit_debug(u
, "Time change, recalculating next elapse.");
853 timer_enter_waiting(t
, true);
857 static void timer_timezone_change(Unit
*u
) {
858 Timer
*t
= ASSERT_PTR(TIMER(u
));
860 if (t
->state
!= TIMER_WAITING
)
863 if (t
->on_timezone_change
) {
864 log_unit_debug(u
, "Timezone change, triggering activation.");
865 timer_enter_running(t
);
867 log_unit_debug(u
, "Timezone change, recalculating next elapse.");
868 timer_enter_waiting(t
, false);
872 static int timer_clean(Unit
*u
, ExecCleanMask mask
) {
873 Timer
*t
= ASSERT_PTR(TIMER(u
));
878 if (t
->state
!= TIMER_DEAD
)
881 if (mask
!= EXEC_CLEAN_STATE
)
884 r
= timer_setup_persistent(t
);
891 if (unlink(t
->stamp_path
) && errno
!= ENOENT
)
892 return log_unit_error_errno(u
, errno
, "Failed to clean stamp file of timer: %m");
897 static int timer_can_clean(Unit
*u
, ExecCleanMask
*ret
) {
898 Timer
*t
= ASSERT_PTR(TIMER(u
));
902 *ret
= t
->persistent
? EXEC_CLEAN_STATE
: 0;
906 static int timer_can_start(Unit
*u
) {
907 Timer
*t
= ASSERT_PTR(TIMER(u
));
910 r
= unit_test_start_limit(u
);
912 timer_enter_dead(t
, TIMER_FAILURE_START_LIMIT_HIT
);
919 static void activation_details_timer_serialize(const ActivationDetails
*details
, FILE *f
) {
920 const ActivationDetailsTimer
*t
= ASSERT_PTR(ACTIVATION_DETAILS_TIMER(details
));
925 (void) serialize_dual_timestamp(f
, "activation-details-timer-last-trigger", &t
->last_trigger
);
928 static int activation_details_timer_deserialize(const char *key
, const char *value
, ActivationDetails
**details
) {
934 if (!details
|| !*details
)
937 ActivationDetailsTimer
*t
= ACTIVATION_DETAILS_TIMER(*details
);
941 if (!streq(key
, "activation-details-timer-last-trigger"))
944 r
= deserialize_dual_timestamp(value
, &t
->last_trigger
);
951 static int activation_details_timer_append_env(const ActivationDetails
*details
, char ***strv
) {
952 const ActivationDetailsTimer
*t
= ASSERT_PTR(ACTIVATION_DETAILS_TIMER(details
));
958 if (!dual_timestamp_is_set(&t
->last_trigger
))
961 r
= strv_extendf(strv
, "TRIGGER_TIMER_REALTIME_USEC=" USEC_FMT
, t
->last_trigger
.realtime
);
965 r
= strv_extendf(strv
, "TRIGGER_TIMER_MONOTONIC_USEC=" USEC_FMT
, t
->last_trigger
.monotonic
);
969 return 2; /* Return the number of variables added to the env block */
972 static int activation_details_timer_append_pair(const ActivationDetails
*details
, char ***strv
) {
973 const ActivationDetailsTimer
*t
= ASSERT_PTR(ACTIVATION_DETAILS_TIMER(details
));
979 if (!dual_timestamp_is_set(&t
->last_trigger
))
982 r
= strv_extend(strv
, "trigger_timer_realtime_usec");
986 r
= strv_extendf(strv
, USEC_FMT
, t
->last_trigger
.realtime
);
990 r
= strv_extend(strv
, "trigger_timer_monotonic_usec");
994 r
= strv_extendf(strv
, USEC_FMT
, t
->last_trigger
.monotonic
);
998 return 2; /* Return the number of pairs added to the env block */
1001 uint64_t timer_next_elapse_monotonic(const Timer
*t
) {
1004 return (uint64_t) usec_shift_clock(t
->next_elapse_monotonic_or_boottime
,
1005 TIMER_MONOTONIC_CLOCK(t
), CLOCK_MONOTONIC
);
1008 static const char* const timer_base_table
[_TIMER_BASE_MAX
] = {
1009 [TIMER_ACTIVE
] = "OnActiveSec",
1010 [TIMER_BOOT
] = "OnBootSec",
1011 [TIMER_STARTUP
] = "OnStartupSec",
1012 [TIMER_UNIT_ACTIVE
] = "OnUnitActiveSec",
1013 [TIMER_UNIT_INACTIVE
] = "OnUnitInactiveSec",
1014 [TIMER_CALENDAR
] = "OnCalendar",
1017 DEFINE_STRING_TABLE_LOOKUP(timer_base
, TimerBase
);
1019 char* timer_base_to_usec_string(TimerBase i
) {
1020 _cleanup_free_
char *buf
= NULL
;
1024 s
= timer_base_to_string(i
);
1026 if (endswith(s
, "Sec")) {
1029 buf
= new(char, l
+2);
1033 memcpy(buf
, s
, l
-3);
1034 memcpy(buf
+l
-3, "USec", 5);
1041 return TAKE_PTR(buf
);
1044 static const char* const timer_result_table
[_TIMER_RESULT_MAX
] = {
1045 [TIMER_SUCCESS
] = "success",
1046 [TIMER_FAILURE_RESOURCES
] = "resources",
1047 [TIMER_FAILURE_START_LIMIT_HIT
] = "start-limit-hit",
1050 DEFINE_STRING_TABLE_LOOKUP(timer_result
, TimerResult
);
1052 const UnitVTable timer_vtable
= {
1053 .object_size
= sizeof(Timer
),
1059 .private_section
= "Timer",
1061 .can_transient
= true,
1063 .can_trigger
= true,
1069 .coldplug
= timer_coldplug
,
1073 .start
= timer_start
,
1076 .clean
= timer_clean
,
1077 .can_clean
= timer_can_clean
,
1079 .serialize
= timer_serialize
,
1080 .deserialize_item
= timer_deserialize_item
,
1082 .active_state
= timer_active_state
,
1083 .sub_state_to_string
= timer_sub_state_to_string
,
1085 .trigger_notify
= timer_trigger_notify
,
1087 .reset_failed
= timer_reset_failed
,
1088 .time_change
= timer_time_change
,
1089 .timezone_change
= timer_timezone_change
,
1091 .bus_set_property
= bus_timer_set_property
,
1093 .can_start
= timer_can_start
,
1096 const ActivationDetailsVTable activation_details_timer_vtable
= {
1097 .object_size
= sizeof(ActivationDetailsTimer
),
1099 .serialize
= activation_details_timer_serialize
,
1100 .deserialize
= activation_details_timer_deserialize
,
1101 .append_env
= activation_details_timer_append_env
,
1102 .append_pair
= activation_details_timer_append_pair
,