Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <sys/stat.h>
4 : #include <sys/types.h>
5 : #include <unistd.h>
6 :
7 : #include <errno.h>
8 :
9 : #include "alloc-util.h"
10 : #include "bus-error.h"
11 : #include "bus-util.h"
12 : #include "dbus-timer.h"
13 : #include "dbus-unit.h"
14 : #include "fs-util.h"
15 : #include "parse-util.h"
16 : #include "random-util.h"
17 : #include "serialize.h"
18 : #include "special.h"
19 : #include "string-table.h"
20 : #include "string-util.h"
21 : #include "timer.h"
22 : #include "unit-name.h"
23 : #include "unit.h"
24 : #include "user-util.h"
25 : #include "virt.h"
26 :
27 : static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
28 : [TIMER_DEAD] = UNIT_INACTIVE,
29 : [TIMER_WAITING] = UNIT_ACTIVE,
30 : [TIMER_RUNNING] = UNIT_ACTIVE,
31 : [TIMER_ELAPSED] = UNIT_ACTIVE,
32 : [TIMER_FAILED] = UNIT_FAILED
33 : };
34 :
35 : static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
36 :
37 0 : static void timer_init(Unit *u) {
38 0 : Timer *t = TIMER(u);
39 :
40 0 : assert(u);
41 0 : assert(u->load_state == UNIT_STUB);
42 :
43 0 : t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
44 0 : t->next_elapse_realtime = USEC_INFINITY;
45 0 : t->accuracy_usec = u->manager->default_timer_accuracy_usec;
46 0 : t->remain_after_elapse = true;
47 0 : }
48 :
49 0 : void timer_free_values(Timer *t) {
50 : TimerValue *v;
51 :
52 0 : assert(t);
53 :
54 0 : while ((v = t->values)) {
55 0 : LIST_REMOVE(value, t->values, v);
56 0 : calendar_spec_free(v->calendar_spec);
57 0 : free(v);
58 : }
59 0 : }
60 :
61 0 : static void timer_done(Unit *u) {
62 0 : Timer *t = TIMER(u);
63 :
64 0 : assert(t);
65 :
66 0 : timer_free_values(t);
67 :
68 0 : t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
69 0 : t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
70 :
71 0 : free(t->stamp_path);
72 0 : }
73 :
74 0 : static int timer_verify(Timer *t) {
75 0 : assert(t);
76 :
77 0 : if (UNIT(t)->load_state != UNIT_LOADED)
78 0 : return 0;
79 :
80 0 : if (!t->values && !t->on_clock_change && !t->on_timezone_change) {
81 0 : log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing.");
82 0 : return -ENOEXEC;
83 : }
84 :
85 0 : return 0;
86 : }
87 :
88 0 : static int timer_add_default_dependencies(Timer *t) {
89 : int r;
90 : TimerValue *v;
91 :
92 0 : assert(t);
93 :
94 0 : if (!UNIT(t)->default_dependencies)
95 0 : return 0;
96 :
97 0 : r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
98 0 : if (r < 0)
99 0 : return r;
100 :
101 0 : if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
102 0 : r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
103 0 : if (r < 0)
104 0 : return r;
105 :
106 0 : LIST_FOREACH(value, v, t->values) {
107 0 : if (v->base == TIMER_CALENDAR) {
108 0 : r = unit_add_dependency_by_name(UNIT(t), UNIT_AFTER, SPECIAL_TIME_SYNC_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
109 0 : if (r < 0)
110 0 : return r;
111 0 : break;
112 : }
113 : }
114 : }
115 :
116 0 : return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
117 : }
118 :
119 0 : static int timer_add_trigger_dependencies(Timer *t) {
120 : Unit *x;
121 : int r;
122 :
123 0 : assert(t);
124 :
125 0 : if (!hashmap_isempty(UNIT(t)->dependencies[UNIT_TRIGGERS]))
126 0 : return 0;
127 :
128 0 : r = unit_load_related_unit(UNIT(t), ".service", &x);
129 0 : if (r < 0)
130 0 : return r;
131 :
132 0 : return unit_add_two_dependencies(UNIT(t), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT);
133 : }
134 :
135 0 : static int timer_setup_persistent(Timer *t) {
136 : int r;
137 :
138 0 : assert(t);
139 :
140 0 : if (!t->persistent)
141 0 : return 0;
142 :
143 0 : if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
144 :
145 0 : r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE);
146 0 : if (r < 0)
147 0 : return r;
148 :
149 0 : t->stamp_path = strjoin("/var/lib/systemd/timers/stamp-", UNIT(t)->id);
150 : } else {
151 : const char *e;
152 :
153 0 : e = getenv("XDG_DATA_HOME");
154 0 : if (e)
155 0 : t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id);
156 : else {
157 :
158 0 : _cleanup_free_ char *h = NULL;
159 :
160 0 : r = get_home_dir(&h);
161 0 : if (r < 0)
162 0 : return log_unit_error_errno(UNIT(t), r, "Failed to determine home directory: %m");
163 :
164 0 : t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id);
165 : }
166 : }
167 :
168 0 : if (!t->stamp_path)
169 0 : return log_oom();
170 :
171 0 : return 0;
172 : }
173 :
174 0 : static int timer_load(Unit *u) {
175 0 : Timer *t = TIMER(u);
176 : int r;
177 :
178 0 : assert(u);
179 0 : assert(u->load_state == UNIT_STUB);
180 :
181 0 : r = unit_load_fragment_and_dropin(u);
182 0 : if (r < 0)
183 0 : return r;
184 :
185 0 : if (u->load_state == UNIT_LOADED) {
186 :
187 0 : r = timer_add_trigger_dependencies(t);
188 0 : if (r < 0)
189 0 : return r;
190 :
191 0 : r = timer_setup_persistent(t);
192 0 : if (r < 0)
193 0 : return r;
194 :
195 0 : r = timer_add_default_dependencies(t);
196 0 : if (r < 0)
197 0 : return r;
198 : }
199 :
200 0 : return timer_verify(t);
201 : }
202 :
203 0 : static void timer_dump(Unit *u, FILE *f, const char *prefix) {
204 : char buf[FORMAT_TIMESPAN_MAX];
205 0 : Timer *t = TIMER(u);
206 : Unit *trigger;
207 : TimerValue *v;
208 :
209 0 : trigger = UNIT_TRIGGER(u);
210 :
211 0 : fprintf(f,
212 : "%sTimer State: %s\n"
213 : "%sResult: %s\n"
214 : "%sUnit: %s\n"
215 : "%sPersistent: %s\n"
216 : "%sWakeSystem: %s\n"
217 : "%sAccuracy: %s\n"
218 : "%sRemainAfterElapse: %s\n"
219 : "%sOnClockChange: %s\n"
220 : "%sOnTimeZoneChange %s\n",
221 : prefix, timer_state_to_string(t->state),
222 : prefix, timer_result_to_string(t->result),
223 : prefix, trigger ? trigger->id : "n/a",
224 0 : prefix, yes_no(t->persistent),
225 0 : prefix, yes_no(t->wake_system),
226 : prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1),
227 0 : prefix, yes_no(t->remain_after_elapse),
228 0 : prefix, yes_no(t->on_clock_change),
229 0 : prefix, yes_no(t->on_timezone_change));
230 :
231 0 : LIST_FOREACH(value, v, t->values) {
232 :
233 0 : if (v->base == TIMER_CALENDAR) {
234 0 : _cleanup_free_ char *p = NULL;
235 :
236 0 : (void) calendar_spec_to_string(v->calendar_spec, &p);
237 :
238 0 : fprintf(f,
239 : "%s%s: %s\n",
240 : prefix,
241 : timer_base_to_string(v->base),
242 : strna(p));
243 : } else {
244 : char timespan1[FORMAT_TIMESPAN_MAX];
245 :
246 0 : fprintf(f,
247 : "%s%s: %s\n",
248 : prefix,
249 : timer_base_to_string(v->base),
250 : format_timespan(timespan1, sizeof(timespan1), v->value, 0));
251 : }
252 : }
253 0 : }
254 :
255 0 : static void timer_set_state(Timer *t, TimerState state) {
256 : TimerState old_state;
257 0 : assert(t);
258 :
259 0 : if (t->state != state)
260 0 : bus_unit_send_pending_change_signal(UNIT(t), false);
261 :
262 0 : old_state = t->state;
263 0 : t->state = state;
264 :
265 0 : if (state != TIMER_WAITING) {
266 0 : t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
267 0 : t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
268 0 : t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
269 0 : t->next_elapse_realtime = USEC_INFINITY;
270 : }
271 :
272 0 : if (state != old_state)
273 0 : log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state));
274 :
275 0 : unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
276 0 : }
277 :
278 : static void timer_enter_waiting(Timer *t, bool time_change);
279 :
280 0 : static int timer_coldplug(Unit *u) {
281 0 : Timer *t = TIMER(u);
282 :
283 0 : assert(t);
284 0 : assert(t->state == TIMER_DEAD);
285 :
286 0 : if (t->deserialized_state == t->state)
287 0 : return 0;
288 :
289 0 : if (t->deserialized_state == TIMER_WAITING)
290 0 : timer_enter_waiting(t, false);
291 : else
292 0 : timer_set_state(t, t->deserialized_state);
293 :
294 0 : return 0;
295 : }
296 :
297 0 : static void timer_enter_dead(Timer *t, TimerResult f) {
298 0 : assert(t);
299 :
300 0 : if (t->result == TIMER_SUCCESS)
301 0 : t->result = f;
302 :
303 0 : unit_log_result(UNIT(t), t->result == TIMER_SUCCESS, timer_result_to_string(t->result));
304 0 : timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
305 0 : }
306 :
307 0 : static void timer_enter_elapsed(Timer *t, bool leave_around) {
308 0 : assert(t);
309 :
310 : /* If a unit is marked with RemainAfterElapse=yes we leave it
311 : * around even after it elapsed once, so that starting it
312 : * later again does not necessarily mean immediate
313 : * retriggering. We unconditionally leave units with
314 : * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around,
315 : * since they might be restarted automatically at any time
316 : * later on. */
317 :
318 0 : if (t->remain_after_elapse || leave_around)
319 0 : timer_set_state(t, TIMER_ELAPSED);
320 : else
321 0 : timer_enter_dead(t, TIMER_SUCCESS);
322 0 : }
323 :
324 0 : static void add_random(Timer *t, usec_t *v) {
325 : char s[FORMAT_TIMESPAN_MAX];
326 : usec_t add;
327 :
328 0 : assert(t);
329 0 : assert(v);
330 :
331 0 : if (t->random_usec == 0)
332 0 : return;
333 0 : if (*v == USEC_INFINITY)
334 0 : return;
335 :
336 0 : add = random_u64() % t->random_usec;
337 :
338 0 : if (*v + add < *v) /* overflow */
339 0 : *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
340 : else
341 0 : *v += add;
342 :
343 0 : log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
344 : }
345 :
346 0 : static void timer_enter_waiting(Timer *t, bool time_change) {
347 0 : bool found_monotonic = false, found_realtime = false;
348 0 : bool leave_around = false;
349 : triple_timestamp ts;
350 : TimerValue *v;
351 : Unit *trigger;
352 : int r;
353 :
354 0 : assert(t);
355 :
356 0 : trigger = UNIT_TRIGGER(UNIT(t));
357 0 : if (!trigger) {
358 0 : log_unit_error(UNIT(t), "Unit to trigger vanished.");
359 0 : timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
360 0 : return;
361 : }
362 :
363 0 : triple_timestamp_get(&ts);
364 0 : t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
365 :
366 0 : LIST_FOREACH(value, v, t->values) {
367 0 : if (v->disabled)
368 0 : continue;
369 :
370 0 : if (v->base == TIMER_CALENDAR) {
371 : usec_t b;
372 :
373 : /* If we know the last time this was
374 : * triggered, schedule the job based relative
375 : * to that. If we don't, just start from
376 : * the activation time. */
377 :
378 0 : if (t->last_trigger.realtime > 0)
379 0 : b = t->last_trigger.realtime;
380 : else {
381 0 : if (state_translation_table[t->state] == UNIT_ACTIVE)
382 0 : b = UNIT(t)->inactive_exit_timestamp.realtime;
383 : else
384 0 : b = ts.realtime;
385 : }
386 :
387 0 : r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
388 0 : if (r < 0)
389 0 : continue;
390 :
391 : /* To make the delay due to RandomizedDelaySec= work even at boot,
392 : * if the scheduled time has already passed, set the time when systemd
393 : * first started as the scheduled time.
394 : * Also, we don't have to check t->persistent since the logic implicitly express true. */
395 0 : if (v->next_elapse < UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime)
396 0 : v->next_elapse = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime;
397 :
398 0 : if (!found_realtime)
399 0 : t->next_elapse_realtime = v->next_elapse;
400 : else
401 0 : t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
402 :
403 0 : found_realtime = true;
404 :
405 : } else {
406 : usec_t base;
407 :
408 0 : switch (v->base) {
409 :
410 0 : case TIMER_ACTIVE:
411 0 : if (state_translation_table[t->state] == UNIT_ACTIVE)
412 0 : base = UNIT(t)->inactive_exit_timestamp.monotonic;
413 : else
414 0 : base = ts.monotonic;
415 0 : break;
416 :
417 0 : case TIMER_BOOT:
418 0 : if (detect_container() <= 0) {
419 : /* CLOCK_MONOTONIC equals the uptime on Linux */
420 0 : base = 0;
421 0 : break;
422 : }
423 : /* In a container we don't want to include the time the host
424 : * was already up when the container started, so count from
425 : * our own startup. */
426 : _fallthrough_;
427 : case TIMER_STARTUP:
428 0 : base = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic;
429 0 : break;
430 :
431 0 : case TIMER_UNIT_ACTIVE:
432 0 : leave_around = true;
433 0 : base = MAX(trigger->inactive_exit_timestamp.monotonic, t->last_trigger.monotonic);
434 0 : if (base <= 0)
435 0 : continue;
436 0 : break;
437 :
438 0 : case TIMER_UNIT_INACTIVE:
439 0 : leave_around = true;
440 0 : base = MAX(trigger->inactive_enter_timestamp.monotonic, t->last_trigger.monotonic);
441 0 : if (base <= 0)
442 0 : continue;
443 0 : break;
444 :
445 0 : default:
446 0 : assert_not_reached("Unknown timer base");
447 : }
448 :
449 0 : v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value);
450 :
451 0 : if (dual_timestamp_is_set(&t->last_trigger) &&
452 0 : !time_change &&
453 0 : v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) &&
454 0 : IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
455 : /* This is a one time trigger, disable it now */
456 0 : v->disabled = true;
457 0 : continue;
458 : }
459 :
460 0 : if (!found_monotonic)
461 0 : t->next_elapse_monotonic_or_boottime = v->next_elapse;
462 : else
463 0 : t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse);
464 :
465 0 : found_monotonic = true;
466 : }
467 : }
468 :
469 0 : if (!found_monotonic && !found_realtime && !t->on_timezone_change && !t->on_clock_change) {
470 0 : log_unit_debug(UNIT(t), "Timer is elapsed.");
471 0 : timer_enter_elapsed(t, leave_around);
472 0 : return;
473 : }
474 :
475 0 : if (found_monotonic) {
476 : char buf[FORMAT_TIMESPAN_MAX];
477 : usec_t left;
478 :
479 0 : add_random(t, &t->next_elapse_monotonic_or_boottime);
480 :
481 0 : left = usec_sub_unsigned(t->next_elapse_monotonic_or_boottime, triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)));
482 0 : log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
483 :
484 0 : if (t->monotonic_event_source) {
485 0 : r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
486 0 : if (r < 0)
487 0 : goto fail;
488 :
489 0 : r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
490 0 : if (r < 0)
491 0 : goto fail;
492 : } else {
493 :
494 0 : r = sd_event_add_time(
495 0 : UNIT(t)->manager->event,
496 : &t->monotonic_event_source,
497 0 : t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC,
498 : t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
499 : timer_dispatch, t);
500 0 : if (r < 0)
501 0 : goto fail;
502 :
503 0 : (void) sd_event_source_set_description(t->monotonic_event_source, "timer-monotonic");
504 : }
505 :
506 0 : } else if (t->monotonic_event_source) {
507 :
508 0 : r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
509 0 : if (r < 0)
510 0 : goto fail;
511 : }
512 :
513 0 : if (found_realtime) {
514 : char buf[FORMAT_TIMESTAMP_MAX];
515 :
516 0 : add_random(t, &t->next_elapse_realtime);
517 :
518 0 : log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
519 :
520 0 : if (t->realtime_event_source) {
521 0 : r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
522 0 : if (r < 0)
523 0 : goto fail;
524 :
525 0 : r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
526 0 : if (r < 0)
527 0 : goto fail;
528 : } else {
529 0 : r = sd_event_add_time(
530 0 : UNIT(t)->manager->event,
531 : &t->realtime_event_source,
532 0 : t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME,
533 : t->next_elapse_realtime, t->accuracy_usec,
534 : timer_dispatch, t);
535 0 : if (r < 0)
536 0 : goto fail;
537 :
538 0 : (void) sd_event_source_set_description(t->realtime_event_source, "timer-realtime");
539 : }
540 :
541 0 : } else if (t->realtime_event_source) {
542 :
543 0 : r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
544 0 : if (r < 0)
545 0 : goto fail;
546 : }
547 :
548 0 : timer_set_state(t, TIMER_WAITING);
549 0 : return;
550 :
551 0 : fail:
552 0 : log_unit_warning_errno(UNIT(t), r, "Failed to enter waiting state: %m");
553 0 : timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
554 : }
555 :
556 0 : static void timer_enter_running(Timer *t) {
557 0 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
558 : Unit *trigger;
559 : int r;
560 :
561 0 : assert(t);
562 :
563 : /* Don't start job if we are supposed to go down */
564 0 : if (unit_stop_pending(UNIT(t)))
565 0 : return;
566 :
567 0 : trigger = UNIT_TRIGGER(UNIT(t));
568 0 : if (!trigger) {
569 0 : log_unit_error(UNIT(t), "Unit to trigger vanished.");
570 0 : timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
571 0 : return;
572 : }
573 :
574 0 : r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
575 0 : if (r < 0)
576 0 : goto fail;
577 :
578 0 : dual_timestamp_get(&t->last_trigger);
579 :
580 0 : if (t->stamp_path)
581 0 : touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID);
582 :
583 0 : timer_set_state(t, TIMER_RUNNING);
584 0 : return;
585 :
586 0 : fail:
587 0 : log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
588 0 : timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
589 : }
590 :
591 0 : static int timer_start(Unit *u) {
592 0 : Timer *t = TIMER(u);
593 : TimerValue *v;
594 : int r;
595 :
596 0 : assert(t);
597 0 : assert(IN_SET(t->state, TIMER_DEAD, TIMER_FAILED));
598 :
599 0 : r = unit_test_trigger_loaded(u);
600 0 : if (r < 0)
601 0 : return r;
602 :
603 0 : r = unit_test_start_limit(u);
604 0 : if (r < 0) {
605 0 : timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
606 0 : return r;
607 : }
608 :
609 0 : r = unit_acquire_invocation_id(u);
610 0 : if (r < 0)
611 0 : return r;
612 :
613 0 : t->last_trigger = DUAL_TIMESTAMP_NULL;
614 :
615 : /* Reenable all timers that depend on unit activation time */
616 0 : LIST_FOREACH(value, v, t->values)
617 0 : if (v->base == TIMER_ACTIVE)
618 0 : v->disabled = false;
619 :
620 0 : if (t->stamp_path) {
621 : struct stat st;
622 :
623 0 : if (stat(t->stamp_path, &st) >= 0) {
624 : usec_t ft;
625 :
626 : /* Load the file timestamp, but only if it is actually in the past. If it is in the future,
627 : * something is wrong with the system clock. */
628 :
629 0 : ft = timespec_load(&st.st_mtim);
630 0 : if (ft < now(CLOCK_REALTIME))
631 0 : t->last_trigger.realtime = ft;
632 : else {
633 : char z[FORMAT_TIMESTAMP_MAX];
634 :
635 0 : log_unit_warning(u, "Not using persistent file timestamp %s as it is in the future.",
636 : format_timestamp(z, sizeof(z), ft));
637 : }
638 :
639 0 : } else if (errno == ENOENT)
640 : /* The timer has never run before,
641 : * make sure a stamp file exists.
642 : */
643 0 : (void) touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
644 : }
645 :
646 0 : t->result = TIMER_SUCCESS;
647 0 : timer_enter_waiting(t, false);
648 0 : return 1;
649 : }
650 :
651 0 : static int timer_stop(Unit *u) {
652 0 : Timer *t = TIMER(u);
653 :
654 0 : assert(t);
655 0 : assert(IN_SET(t->state, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED));
656 :
657 0 : timer_enter_dead(t, TIMER_SUCCESS);
658 0 : return 1;
659 : }
660 :
661 0 : static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
662 0 : Timer *t = TIMER(u);
663 :
664 0 : assert(u);
665 0 : assert(f);
666 0 : assert(fds);
667 :
668 0 : (void) serialize_item(f, "state", timer_state_to_string(t->state));
669 0 : (void) serialize_item(f, "result", timer_result_to_string(t->result));
670 :
671 0 : if (t->last_trigger.realtime > 0)
672 0 : (void) serialize_usec(f, "last-trigger-realtime", t->last_trigger.realtime);
673 :
674 0 : if (t->last_trigger.monotonic > 0)
675 0 : (void) serialize_usec(f, "last-trigger-monotonic", t->last_trigger.monotonic);
676 :
677 0 : return 0;
678 : }
679 :
680 0 : static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
681 0 : Timer *t = TIMER(u);
682 :
683 0 : assert(u);
684 0 : assert(key);
685 0 : assert(value);
686 0 : assert(fds);
687 :
688 0 : if (streq(key, "state")) {
689 : TimerState state;
690 :
691 0 : state = timer_state_from_string(value);
692 0 : if (state < 0)
693 0 : log_unit_debug(u, "Failed to parse state value: %s", value);
694 : else
695 0 : t->deserialized_state = state;
696 :
697 0 : } else if (streq(key, "result")) {
698 : TimerResult f;
699 :
700 0 : f = timer_result_from_string(value);
701 0 : if (f < 0)
702 0 : log_unit_debug(u, "Failed to parse result value: %s", value);
703 0 : else if (f != TIMER_SUCCESS)
704 0 : t->result = f;
705 :
706 0 : } else if (streq(key, "last-trigger-realtime"))
707 0 : (void) deserialize_usec(value, &t->last_trigger.realtime);
708 0 : else if (streq(key, "last-trigger-monotonic"))
709 0 : (void) deserialize_usec(value, &t->last_trigger.monotonic);
710 : else
711 0 : log_unit_debug(u, "Unknown serialization key: %s", key);
712 :
713 0 : return 0;
714 : }
715 :
716 0 : _pure_ static UnitActiveState timer_active_state(Unit *u) {
717 0 : assert(u);
718 :
719 0 : return state_translation_table[TIMER(u)->state];
720 : }
721 :
722 0 : _pure_ static const char *timer_sub_state_to_string(Unit *u) {
723 0 : assert(u);
724 :
725 0 : return timer_state_to_string(TIMER(u)->state);
726 : }
727 :
728 0 : static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
729 0 : Timer *t = TIMER(userdata);
730 :
731 0 : assert(t);
732 :
733 0 : if (t->state != TIMER_WAITING)
734 0 : return 0;
735 :
736 0 : log_unit_debug(UNIT(t), "Timer elapsed.");
737 0 : timer_enter_running(t);
738 0 : return 0;
739 : }
740 :
741 0 : static void timer_trigger_notify(Unit *u, Unit *other) {
742 0 : Timer *t = TIMER(u);
743 : TimerValue *v;
744 :
745 0 : assert(u);
746 0 : assert(other);
747 :
748 0 : if (other->load_state != UNIT_LOADED)
749 0 : return;
750 :
751 : /* Reenable all timers that depend on unit state */
752 0 : LIST_FOREACH(value, v, t->values)
753 0 : if (IN_SET(v->base, TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE))
754 0 : v->disabled = false;
755 :
756 0 : switch (t->state) {
757 :
758 0 : case TIMER_WAITING:
759 : case TIMER_ELAPSED:
760 :
761 : /* Recalculate sleep time */
762 0 : timer_enter_waiting(t, false);
763 0 : break;
764 :
765 0 : case TIMER_RUNNING:
766 :
767 0 : if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
768 0 : log_unit_debug(UNIT(t), "Got notified about unit deactivation.");
769 0 : timer_enter_waiting(t, false);
770 : }
771 0 : break;
772 :
773 0 : case TIMER_DEAD:
774 : case TIMER_FAILED:
775 0 : break;
776 :
777 0 : default:
778 0 : assert_not_reached("Unknown timer state");
779 : }
780 : }
781 :
782 0 : static void timer_reset_failed(Unit *u) {
783 0 : Timer *t = TIMER(u);
784 :
785 0 : assert(t);
786 :
787 0 : if (t->state == TIMER_FAILED)
788 0 : timer_set_state(t, TIMER_DEAD);
789 :
790 0 : t->result = TIMER_SUCCESS;
791 0 : }
792 :
793 0 : static void timer_time_change(Unit *u) {
794 0 : Timer *t = TIMER(u);
795 : usec_t ts;
796 :
797 0 : assert(u);
798 :
799 0 : if (t->state != TIMER_WAITING)
800 0 : return;
801 :
802 : /* If we appear to have triggered in the future, the system clock must
803 : * have been set backwards. So let's rewind our own clock and allow
804 : * the future trigger(s) to happen again :). Exactly the same as when
805 : * you start a timer unit with Persistent=yes. */
806 0 : ts = now(CLOCK_REALTIME);
807 0 : if (t->last_trigger.realtime > ts)
808 0 : t->last_trigger.realtime = ts;
809 :
810 0 : if (t->on_clock_change) {
811 0 : log_unit_debug(u, "Time change, triggering activation.");
812 0 : timer_enter_running(t);
813 : } else {
814 0 : log_unit_debug(u, "Time change, recalculating next elapse.");
815 0 : timer_enter_waiting(t, true);
816 : }
817 : }
818 :
819 0 : static void timer_timezone_change(Unit *u) {
820 0 : Timer *t = TIMER(u);
821 :
822 0 : assert(u);
823 :
824 0 : if (t->state != TIMER_WAITING)
825 0 : return;
826 :
827 0 : if (t->on_timezone_change) {
828 0 : log_unit_debug(u, "Timezone change, triggering activation.");
829 0 : timer_enter_running(t);
830 : } else {
831 0 : log_unit_debug(u, "Timezone change, recalculating next elapse.");
832 0 : timer_enter_waiting(t, false);
833 : }
834 : }
835 :
836 0 : static int timer_clean(Unit *u, ExecCleanMask mask) {
837 0 : Timer *t = TIMER(u);
838 : int r;
839 :
840 0 : assert(t);
841 0 : assert(mask != 0);
842 :
843 0 : if (t->state != TIMER_DEAD)
844 0 : return -EBUSY;
845 :
846 0 : if (!IN_SET(mask, EXEC_CLEAN_STATE))
847 0 : return -EUNATCH;
848 :
849 0 : r = timer_setup_persistent(t);
850 0 : if (r < 0)
851 0 : return r;
852 :
853 0 : if (!t->stamp_path)
854 0 : return -EUNATCH;
855 :
856 0 : if (unlink(t->stamp_path) && errno != ENOENT)
857 0 : return log_unit_error_errno(u, errno, "Failed to clean stamp file of timer: %m");
858 :
859 0 : return 0;
860 : }
861 :
862 0 : static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
863 0 : Timer *t = TIMER(u);
864 :
865 0 : assert(t);
866 :
867 0 : *ret = t->persistent ? EXEC_CLEAN_STATE : 0;
868 0 : return 0;
869 : }
870 :
871 : static const char* const timer_base_table[_TIMER_BASE_MAX] = {
872 : [TIMER_ACTIVE] = "OnActiveSec",
873 : [TIMER_BOOT] = "OnBootSec",
874 : [TIMER_STARTUP] = "OnStartupSec",
875 : [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
876 : [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
877 : [TIMER_CALENDAR] = "OnCalendar"
878 : };
879 :
880 16 : DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
881 :
882 : static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
883 : [TIMER_SUCCESS] = "success",
884 : [TIMER_FAILURE_RESOURCES] = "resources",
885 : [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
886 : };
887 :
888 10 : DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
889 :
890 : const UnitVTable timer_vtable = {
891 : .object_size = sizeof(Timer),
892 :
893 : .sections =
894 : "Unit\0"
895 : "Timer\0"
896 : "Install\0",
897 : .private_section = "Timer",
898 :
899 : .init = timer_init,
900 : .done = timer_done,
901 : .load = timer_load,
902 :
903 : .coldplug = timer_coldplug,
904 :
905 : .dump = timer_dump,
906 :
907 : .start = timer_start,
908 : .stop = timer_stop,
909 :
910 : .clean = timer_clean,
911 : .can_clean = timer_can_clean,
912 :
913 : .serialize = timer_serialize,
914 : .deserialize_item = timer_deserialize_item,
915 :
916 : .active_state = timer_active_state,
917 : .sub_state_to_string = timer_sub_state_to_string,
918 :
919 : .trigger_notify = timer_trigger_notify,
920 :
921 : .reset_failed = timer_reset_failed,
922 : .time_change = timer_time_change,
923 : .timezone_change = timer_timezone_change,
924 :
925 : .bus_vtable = bus_timer_vtable,
926 : .bus_set_property = bus_timer_set_property,
927 :
928 : .can_transient = true,
929 : };
|