Bug Summary

File:build-scan/../src/core/timer.c
Warning:line 49, column 17
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name timer.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/core/libcore.a.p -I src/core -I ../src/core -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/libmount -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/core/timer.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4
5#include "alloc-util.h"
6#include "bus-error.h"
7#include "bus-util.h"
8#include "dbus-timer.h"
9#include "fs-util.h"
10#include "parse-util.h"
11#include "random-util.h"
12#include "special.h"
13#include "string-table.h"
14#include "string-util.h"
15#include "timer.h"
16#include "unit-name.h"
17#include "unit.h"
18#include "user-util.h"
19#include "virt.h"
20
21static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
22 [TIMER_DEAD] = UNIT_INACTIVE,
23 [TIMER_WAITING] = UNIT_ACTIVE,
24 [TIMER_RUNNING] = UNIT_ACTIVE,
25 [TIMER_ELAPSED] = UNIT_ACTIVE,
26 [TIMER_FAILED] = UNIT_FAILED
27};
28
29static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
30
31static void timer_init(Unit *u) {
32 Timer *t = TIMER(u);
33
34 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 34, __PRETTY_FUNCTION__
); } while (0)
;
35 assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB"
), "../src/core/timer.c", 35, __PRETTY_FUNCTION__); } while (
0)
;
36
37 t->next_elapse_monotonic_or_boottime = USEC_INFINITY((usec_t) -1);
38 t->next_elapse_realtime = USEC_INFINITY((usec_t) -1);
39 t->accuracy_usec = u->manager->default_timer_accuracy_usec;
40 t->remain_after_elapse = true1;
41}
42
43void timer_free_values(Timer *t) {
44 TimerValue *v;
45
46 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 46, __PRETTY_FUNCTION__
); } while (0)
;
4
Taking false branch
5
Loop condition is false. Exiting loop
47
48 while ((v = t->values)) {
6
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
49 LIST_REMOVE(value, t->values, v)do { typeof(*(t->values)) **_head = &(t->values), *
_item = (v); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/timer.c", 49, __PRETTY_FUNCTION__
); } while (0); if (_item->value_next) _item->value_next
->value_prev = _item->value_prev; if (_item->value_prev
) _item->value_prev->value_next = _item->value_next;
else { do { if ((__builtin_expect(!!(!(*_head == _item)),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item"
), "../src/core/timer.c", 49, __PRETTY_FUNCTION__); } while (
0); *_head = _item->value_next; } _item->value_next = _item
->value_prev = ((void*)0); } while (0)
;
7
Taking false branch
8
Loop condition is false. Exiting loop
9
Assuming field 'value_next' is null
10
Taking false branch
11
Assuming field 'value_prev' is non-null
12
Taking true branch
13
Loop condition is false. Exiting loop
16
Taking false branch
17
Loop condition is false. Exiting loop
18
Use of memory after it is freed
50 calendar_spec_free(v->calendar_spec);
51 free(v);
14
Memory is released
52 }
53}
54
55static void timer_done(Unit *u) {
56 Timer *t = TIMER(u);
57
58 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 58, __PRETTY_FUNCTION__
); } while (0)
;
1
Taking false branch
2
Loop condition is false. Exiting loop
59
60 timer_free_values(t);
3
Calling 'timer_free_values'
61
62 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
63 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
64
65 free(t->stamp_path);
66}
67
68static int timer_verify(Timer *t) {
69 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 69, __PRETTY_FUNCTION__
); } while (0)
;
70
71 if (UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->load_state != UNIT_LOADED)
72 return 0;
73
74 if (!t->values) {
75 log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing.")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(3, 0, "../src/core/timer.c", 75, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Timer unit lacks value setting. Refusing."
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), 0, "../src/core/timer.c", 75, __func__, "Timer unit lacks value setting. Refusing."
); })
;
76 return -ENOEXEC8;
77 }
78
79 return 0;
80}
81
82static int timer_add_default_dependencies(Timer *t) {
83 int r;
84 TimerValue *v;
85
86 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 86, __PRETTY_FUNCTION__
); } while (0)
;
87
88 if (!UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->default_dependencies)
89 return 0;
90
91 r = unit_add_dependency_by_name(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, UNIT_BEFORE, SPECIAL_TIMERS_TARGET"timers.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT);
92 if (r < 0)
93 return r;
94
95 if (MANAGER_IS_SYSTEM(UNIT(t)->manager)((({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })->manager)->unit_file_scope == UNIT_FILE_SYSTEM
)
) {
96 r = unit_add_two_dependencies_by_name(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET"sysinit.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT);
97 if (r < 0)
98 return r;
99
100 LIST_FOREACH(value, v, t->values)for ((v) = (t->values); (v); (v) = (v)->value_next) {
101 if (v->base == TIMER_CALENDAR) {
102 r = unit_add_dependency_by_name(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, UNIT_AFTER, SPECIAL_TIME_SYNC_TARGET"time-sync.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT);
103 if (r < 0)
104 return r;
105 break;
106 }
107 }
108 }
109
110 return unit_add_two_dependencies_by_name(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET"shutdown.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT);
111}
112
113static int timer_add_trigger_dependencies(Timer *t) {
114 Unit *x;
115 int r;
116
117 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 117, __PRETTY_FUNCTION__
); } while (0)
;
118
119 if (!hashmap_isempty(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->dependencies[UNIT_TRIGGERS]))
120 return 0;
121
122 r = unit_load_related_unit(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, ".service", &x);
123 if (r < 0)
124 return r;
125
126 return unit_add_two_dependencies(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, UNIT_BEFORE, UNIT_TRIGGERS, x, true1, UNIT_DEPENDENCY_IMPLICIT);
127}
128
129static int timer_setup_persistent(Timer *t) {
130 int r;
131
132 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 132, __PRETTY_FUNCTION__
); } while (0)
;
133
134 if (!t->persistent)
135 return 0;
136
137 if (MANAGER_IS_SYSTEM(UNIT(t)->manager)((({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })->manager)->unit_file_scope == UNIT_FILE_SYSTEM
)
) {
138
139 r = unit_require_mounts_for(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE);
140 if (r < 0)
141 return r;
142
143 t->stamp_path = strappend("/var/lib/systemd/timers/stamp-", UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->id);
144 } else {
145 const char *e;
146
147 e = getenv("XDG_DATA_HOME");
148 if (e)
149 t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id)strjoin_real((e), "/systemd/timers/stamp-", ({ typeof(t) _u_ =
(t); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_
; })->id, ((void*)0))
;
150 else {
151
152 _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0);
153
154 r = get_home_dir(&h);
155 if (r < 0)
156 return log_unit_error_errno(UNIT(t), r, "Failed to determine home directory: %m")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(3, r, "../src/core/timer.c", 156, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Failed to determine home directory: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3
))), r, "../src/core/timer.c", 156, __func__, "Failed to determine home directory: %m"
); })
;
157
158 t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id)strjoin_real((h), "/.local/share/systemd/timers/stamp-", ({ typeof
(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta : ((void
*)0); _w_; })->id, ((void*)0))
;
159 }
160 }
161
162 if (!t->stamp_path)
163 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/timer.c", 163
, __func__)
;
164
165 return 0;
166}
167
168static int timer_load(Unit *u) {
169 Timer *t = TIMER(u);
170 int r;
171
172 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 172, __PRETTY_FUNCTION__
); } while (0)
;
173 assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB"
), "../src/core/timer.c", 173, __PRETTY_FUNCTION__); } while (
0)
;
174
175 r = unit_load_fragment_and_dropin(u);
176 if (r < 0)
177 return r;
178
179 if (u->load_state == UNIT_LOADED) {
180
181 r = timer_add_trigger_dependencies(t);
182 if (r < 0)
183 return r;
184
185 r = timer_setup_persistent(t);
186 if (r < 0)
187 return r;
188
189 r = timer_add_default_dependencies(t);
190 if (r < 0)
191 return r;
192 }
193
194 return timer_verify(t);
195}
196
197static void timer_dump(Unit *u, FILE *f, const char *prefix) {
198 char buf[FORMAT_TIMESPAN_MAX64];
199 Timer *t = TIMER(u);
200 Unit *trigger;
201 TimerValue *v;
202
203 trigger = UNIT_TRIGGER(u)((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS
]))
;
204
205 fprintf(f,
206 "%sTimer State: %s\n"
207 "%sResult: %s\n"
208 "%sUnit: %s\n"
209 "%sPersistent: %s\n"
210 "%sWakeSystem: %s\n"
211 "%sAccuracy: %s\n"
212 "%sRemainAfterElapse: %s\n",
213 prefix, timer_state_to_string(t->state),
214 prefix, timer_result_to_string(t->result),
215 prefix, trigger ? trigger->id : "n/a",
216 prefix, yes_no(t->persistent),
217 prefix, yes_no(t->wake_system),
218 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1),
219 prefix, yes_no(t->remain_after_elapse));
220
221 LIST_FOREACH(value, v, t->values)for ((v) = (t->values); (v); (v) = (v)->value_next) {
222
223 if (v->base == TIMER_CALENDAR) {
224 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
225
226 (void) calendar_spec_to_string(v->calendar_spec, &p);
227
228 fprintf(f,
229 "%s%s: %s\n",
230 prefix,
231 timer_base_to_string(v->base),
232 strna(p));
233 } else {
234 char timespan1[FORMAT_TIMESPAN_MAX64];
235
236 fprintf(f,
237 "%s%s: %s\n",
238 prefix,
239 timer_base_to_string(v->base),
240 format_timespan(timespan1, sizeof(timespan1), v->value, 0));
241 }
242 }
243}
244
245static void timer_set_state(Timer *t, TimerState state) {
246 TimerState old_state;
247 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 247, __PRETTY_FUNCTION__
); } while (0)
;
248
249 old_state = t->state;
250 t->state = state;
251
252 if (state != TIMER_WAITING) {
253 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
254 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
255 t->next_elapse_monotonic_or_boottime = USEC_INFINITY((usec_t) -1);
256 t->next_elapse_realtime = USEC_INFINITY((usec_t) -1);
257 }
258
259 if (state != old_state)
260 log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state))({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(7, 0, "../src/core/timer.c", 260, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Changed %s -> %s", timer_state_to_string
(old_state), timer_state_to_string(state)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 260, __func__, "Changed %s -> %s", timer_state_to_string
(old_state), timer_state_to_string(state)); })
;
261
262 unit_notify(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, state_translation_table[old_state], state_translation_table[state], 0);
263}
264
265static void timer_enter_waiting(Timer *t, bool_Bool initial);
266
267static int timer_coldplug(Unit *u) {
268 Timer *t = TIMER(u);
269
270 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 270, __PRETTY_FUNCTION__
); } while (0)
;
271 assert(t->state == TIMER_DEAD)do { if ((__builtin_expect(!!(!(t->state == TIMER_DEAD)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("t->state == TIMER_DEAD"
), "../src/core/timer.c", 271, __PRETTY_FUNCTION__); } while (
0)
;
272
273 if (t->deserialized_state == t->state)
274 return 0;
275
276 if (t->deserialized_state == TIMER_WAITING)
277 timer_enter_waiting(t, false0);
278 else
279 timer_set_state(t, t->deserialized_state);
280
281 return 0;
282}
283
284static void timer_enter_dead(Timer *t, TimerResult f) {
285 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 285, __PRETTY_FUNCTION__
); } while (0)
;
286
287 if (t->result == TIMER_SUCCESS)
288 t->result = f;
289
290 if (t->result == TIMER_SUCCESS)
291 unit_log_success(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
);
292 else
293 unit_log_failure(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
, timer_result_to_string(t->result));
294
295 timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
296}
297
298static void timer_enter_elapsed(Timer *t, bool_Bool leave_around) {
299 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 299, __PRETTY_FUNCTION__
); } while (0)
;
300
301 /* If a unit is marked with RemainAfterElapse=yes we leave it
302 * around even after it elapsed once, so that starting it
303 * later again does not necessarily mean immediate
304 * retriggering. We unconditionally leave units with
305 * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around,
306 * since they might be restarted automatically at any time
307 * later on. */
308
309 if (t->remain_after_elapse || leave_around)
310 timer_set_state(t, TIMER_ELAPSED);
311 else
312 timer_enter_dead(t, TIMER_SUCCESS);
313}
314
315static void add_random(Timer *t, usec_t *v) {
316 char s[FORMAT_TIMESPAN_MAX64];
317 usec_t add;
318
319 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 319, __PRETTY_FUNCTION__
); } while (0)
;
320 assert(v)do { if ((__builtin_expect(!!(!(v)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("v"), "../src/core/timer.c", 320, __PRETTY_FUNCTION__
); } while (0)
;
321
322 if (t->random_usec == 0)
323 return;
324 if (*v == USEC_INFINITY((usec_t) -1))
325 return;
326
327 add = random_u64() % t->random_usec;
328
329 if (*v + add < *v) /* overflow */
330 *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
331 else
332 *v += add;
333
334 log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0))({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(7, 0, "../src/core/timer.c", 334, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Adding %s random time.", format_timespan
(s, sizeof(s), add, 0)) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((7))), 0, "../src/core/timer.c", 334, __func__
, "Adding %s random time.", format_timespan(s, sizeof(s), add
, 0)); })
;
335}
336
337static void timer_enter_waiting(Timer *t, bool_Bool initial) {
338 bool_Bool found_monotonic = false0, found_realtime = false0;
339 bool_Bool leave_around = false0;
340 triple_timestamp ts;
341 TimerValue *v;
342 Unit *trigger;
343 int r;
344
345 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 345, __PRETTY_FUNCTION__
); } while (0)
;
346
347 trigger = UNIT_TRIGGER(UNIT(t))((Unit*) hashmap_first_key((({ typeof(t) _u_ = (t); Unit *_w_
= _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->dependencies
[UNIT_TRIGGERS]))
;
348 if (!trigger) {
349 log_unit_error(UNIT(t), "Unit to trigger vanished.")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(3, 0, "../src/core/timer.c", 349, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Unit to trigger vanished.") :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3)))
, 0, "../src/core/timer.c", 349, __func__, "Unit to trigger vanished."
); })
;
350 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
351 return;
352 }
353
354 triple_timestamp_get(&ts);
355 t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
356
357 LIST_FOREACH(value, v, t->values)for ((v) = (t->values); (v); (v) = (v)->value_next) {
358 if (v->disabled)
359 continue;
360
361 if (v->base == TIMER_CALENDAR) {
362 usec_t b;
363
364 /* If we know the last time this was
365 * triggered, schedule the job based relative
366 * to that. If we don't, just start from
367 * the activation time. */
368
369 if (t->last_trigger.realtime > 0)
370 b = t->last_trigger.realtime;
371 else {
372 if (state_translation_table[t->state] == UNIT_ACTIVE)
373 b = UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->inactive_exit_timestamp.realtime;
374 else
375 b = ts.realtime;
376 }
377
378 r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
379 if (r < 0)
380 continue;
381
382 if (!found_realtime)
383 t->next_elapse_realtime = v->next_elapse;
384 else
385 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse)__extension__ ({ const typeof((t->next_elapse_realtime)) __unique_prefix_A24
= ((t->next_elapse_realtime)); const typeof((v->next_elapse
)) __unique_prefix_B25 = ((v->next_elapse)); __unique_prefix_A24
< __unique_prefix_B25 ? __unique_prefix_A24 : __unique_prefix_B25
; })
;
386
387 found_realtime = true1;
388
389 } else {
390 usec_t base;
391
392 switch (v->base) {
393
394 case TIMER_ACTIVE:
395 if (state_translation_table[t->state] == UNIT_ACTIVE)
396 base = UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->inactive_exit_timestamp.monotonic;
397 else
398 base = ts.monotonic;
399 break;
400
401 case TIMER_BOOT:
402 if (detect_container() <= 0) {
403 /* CLOCK_MONOTONIC equals the uptime on Linux */
404 base = 0;
405 break;
406 }
407 /* In a container we don't want to include the time the host
408 * was already up when the container started, so count from
409 * our own startup. */
410 _fallthrough_;
411 case TIMER_STARTUP:
412 base = UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic;
413 break;
414
415 case TIMER_UNIT_ACTIVE:
416 leave_around = true1;
417 base = trigger->inactive_exit_timestamp.monotonic;
418
419 if (base <= 0)
420 base = t->last_trigger.monotonic;
421
422 if (base <= 0)
423 continue;
424 base = MAX(base, t->last_trigger.monotonic)__extension__ ({ const typeof((base)) __unique_prefix_A26 = (
(base)); const typeof((t->last_trigger.monotonic)) __unique_prefix_B27
= ((t->last_trigger.monotonic)); __unique_prefix_A26 >
__unique_prefix_B27 ? __unique_prefix_A26 : __unique_prefix_B27
; })
;
425
426 break;
427
428 case TIMER_UNIT_INACTIVE:
429 leave_around = true1;
430 base = trigger->inactive_enter_timestamp.monotonic;
431
432 if (base <= 0)
433 base = t->last_trigger.monotonic;
434
435 if (base <= 0)
436 continue;
437 base = MAX(base, t->last_trigger.monotonic)__extension__ ({ const typeof((base)) __unique_prefix_A28 = (
(base)); const typeof((t->last_trigger.monotonic)) __unique_prefix_B29
= ((t->last_trigger.monotonic)); __unique_prefix_A28 >
__unique_prefix_B29 ? __unique_prefix_A28 : __unique_prefix_B29
; })
;
438
439 break;
440
441 default:
442 assert_not_reached("Unknown timer base")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unknown timer base"), "../src/core/timer.c", 442, __PRETTY_FUNCTION__
); } while (0)
;
443 }
444
445 v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC1, TIMER_MONOTONIC_CLOCK(t)((t)->wake_system && clock_boottime_supported() ? 9
: 1)
), v->value);
446
447 if (!initial &&
448 v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)((t)->wake_system && clock_boottime_supported() ? 9
: 1)
) &&
449 IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP}
)/sizeof(int)]; switch(v->base) { case TIMER_ACTIVE: case TIMER_BOOT
: case TIMER_STARTUP: _found = 1; break; default: break; } _found
; })
) {
450 /* This is a one time trigger, disable it now */
451 v->disabled = true1;
452 continue;
453 }
454
455 if (!found_monotonic)
456 t->next_elapse_monotonic_or_boottime = v->next_elapse;
457 else
458 t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse)__extension__ ({ const typeof((t->next_elapse_monotonic_or_boottime
)) __unique_prefix_A30 = ((t->next_elapse_monotonic_or_boottime
)); const typeof((v->next_elapse)) __unique_prefix_B31 = (
(v->next_elapse)); __unique_prefix_A30 < __unique_prefix_B31
? __unique_prefix_A30 : __unique_prefix_B31; })
;
459
460 found_monotonic = true1;
461 }
462 }
463
464 if (!found_monotonic && !found_realtime) {
465 log_unit_debug(UNIT(t), "Timer is elapsed.")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(7, 0, "../src/core/timer.c", 465, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Timer is elapsed.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 465, __func__, "Timer is elapsed."); })
;
466 timer_enter_elapsed(t, leave_around);
467 return;
468 }
469
470 if (found_monotonic) {
471 char buf[FORMAT_TIMESPAN_MAX64];
472 usec_t left;
473
474 add_random(t, &t->next_elapse_monotonic_or_boottime);
475
476 left = usec_sub_unsigned(t->next_elapse_monotonic_or_boottime, triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)((t)->wake_system && clock_boottime_supported() ? 9
: 1)
));
477 log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0))({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(7, 0, "../src/core/timer.c", 477, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Monotonic timer elapses in %s."
, format_timespan(buf, sizeof(buf), left, 0)) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 477, __func__, "Monotonic timer elapses in %s.", format_timespan
(buf, sizeof(buf), left, 0)); })
;
478
479 if (t->monotonic_event_source) {
480 r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
481 if (r < 0)
482 goto fail;
483
484 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
485 if (r < 0)
486 goto fail;
487 } else {
488
489 r = sd_event_add_time(
490 UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->manager->event,
491 &t->monotonic_event_source,
492 t->wake_system ? CLOCK_BOOTTIME_ALARM9 : CLOCK_MONOTONIC1,
493 t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
494 timer_dispatch, t);
495 if (r < 0)
496 goto fail;
497
498 (void) sd_event_source_set_description(t->monotonic_event_source, "timer-monotonic");
499 }
500
501 } else if (t->monotonic_event_source) {
502
503 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
504 if (r < 0)
505 goto fail;
506 }
507
508 if (found_realtime) {
509 char buf[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)];
510
511 add_random(t, &t->next_elapse_realtime);
512
513 log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime))({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(7, 0, "../src/core/timer.c", 513, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Realtime timer elapses at %s."
, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime
)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((
7))), 0, "../src/core/timer.c", 513, __func__, "Realtime timer elapses at %s."
, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime
)); })
;
514
515 if (t->realtime_event_source) {
516 r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
517 if (r < 0)
518 goto fail;
519
520 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
521 if (r < 0)
522 goto fail;
523 } else {
524 r = sd_event_add_time(
525 UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->manager->event,
526 &t->realtime_event_source,
527 t->wake_system ? CLOCK_REALTIME_ALARM8 : CLOCK_REALTIME0,
528 t->next_elapse_realtime, t->accuracy_usec,
529 timer_dispatch, t);
530 if (r < 0)
531 goto fail;
532
533 (void) sd_event_source_set_description(t->realtime_event_source, "timer-realtime");
534 }
535
536 } else if (t->realtime_event_source) {
537
538 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
539 if (r < 0)
540 goto fail;
541 }
542
543 timer_set_state(t, TIMER_WAITING);
544 return;
545
546fail:
547 log_unit_warning_errno(UNIT(t), r, "Failed to enter waiting state: %m")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(4, r, "../src/core/timer.c", 547, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Failed to enter waiting state: %m"
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4
))), r, "../src/core/timer.c", 547, __func__, "Failed to enter waiting state: %m"
); })
;
548 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
549}
550
551static void timer_enter_running(Timer *t) {
552 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
553 Unit *trigger;
554 int r;
555
556 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 556, __PRETTY_FUNCTION__
); } while (0)
;
557
558 /* Don't start job if we are supposed to go down */
559 if (unit_stop_pending(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
))
560 return;
561
562 trigger = UNIT_TRIGGER(UNIT(t))((Unit*) hashmap_first_key((({ typeof(t) _u_ = (t); Unit *_w_
= _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->dependencies
[UNIT_TRIGGERS]))
;
563 if (!trigger) {
564 log_unit_error(UNIT(t), "Unit to trigger vanished.")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(3, 0, "../src/core/timer.c", 564, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Unit to trigger vanished.") :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3)))
, 0, "../src/core/timer.c", 564, __func__, "Unit to trigger vanished."
); })
;
565 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
566 return;
567 }
568
569 r = manager_add_job(UNIT(t)({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ? &(_u_)->meta
: ((void*)0); _w_; })
->manager, JOB_START, trigger, JOB_REPLACE, NULL((void*)0), &error, NULL((void*)0));
570 if (r < 0)
571 goto fail;
572
573 dual_timestamp_get(&t->last_trigger);
574
575 if (t->stamp_path)
576 touch_file(t->stamp_path, true1, t->last_trigger.realtime, UID_INVALID((uid_t) -1), GID_INVALID((gid_t) -1), MODE_INVALID((mode_t) -1));
577
578 timer_set_state(t, TIMER_RUNNING);
579 return;
580
581fail:
582 log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r))({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(4, 0, "../src/core/timer.c", 582, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Failed to queue unit startup job: %s"
, bus_error_message(&error, r)) : log_internal_realm(((LOG_REALM_SYSTEMD
) << 10 | ((4))), 0, "../src/core/timer.c", 582, __func__
, "Failed to queue unit startup job: %s", bus_error_message(&
error, r)); })
;
583 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
584}
585
586static int timer_start(Unit *u) {
587 Timer *t = TIMER(u);
588 TimerValue *v;
589 Unit *trigger;
590 int r;
591
592 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 592, __PRETTY_FUNCTION__
); } while (0)
;
593 assert(IN_SET(t->state, TIMER_DEAD, TIMER_FAILED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__
((unused)) char _static_assert__macros_need_to_be_extended[20
- sizeof((int[]){TIMER_DEAD, TIMER_FAILED})/sizeof(int)]; switch
(t->state) { case TIMER_DEAD: case TIMER_FAILED: _found = 1
; break; default: break; } _found; }))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("IN_SET(t->state, TIMER_DEAD, TIMER_FAILED)"
), "../src/core/timer.c", 593, __PRETTY_FUNCTION__); } while (
0)
;
594
595 trigger = UNIT_TRIGGER(u)((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS
]))
;
596 if (!trigger || trigger->load_state != UNIT_LOADED) {
597 log_unit_error(u, "Refusing to start, unit to trigger not loaded.")({ const Unit *_u = (u); _u ? log_object_internal(3, 0, "../src/core/timer.c"
, 597, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Refusing to start, unit to trigger not loaded.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/timer.c"
, 597, __func__, "Refusing to start, unit to trigger not loaded."
); })
;
598 return -ENOENT2;
599 }
600
601 r = unit_start_limit_test(u);
602 if (r < 0) {
603 timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
604 return r;
605 }
606
607 r = unit_acquire_invocation_id(u);
608 if (r < 0)
609 return r;
610
611 t->last_trigger = DUAL_TIMESTAMP_NULL((struct dual_timestamp) {});
612
613 /* Reenable all timers that depend on unit activation time */
614 LIST_FOREACH(value, v, t->values)for ((v) = (t->values); (v); (v) = (v)->value_next)
615 if (v->base == TIMER_ACTIVE)
616 v->disabled = false0;
617
618 if (t->stamp_path) {
619 struct stat st;
620
621 if (stat(t->stamp_path, &st) >= 0) {
622 usec_t ft;
623
624 /* Load the file timestamp, but only if it is actually in the past. If it is in the future,
625 * something is wrong with the system clock. */
626
627 ft = timespec_load(&st.st_mtim);
628 if (ft < now(CLOCK_REALTIME0))
629 t->last_trigger.realtime = ft;
630 else {
631 char z[FORMAT_TIMESTAMP_MAX(3+1+10+1+8+1+6+1+6+1)];
632
633 log_unit_warning(u, "Not using persistent file timestamp %s as it is in the future.",({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/timer.c"
, 634, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Not using persistent file timestamp %s as it is in the future."
, format_timestamp(z, sizeof(z), ft)) : log_internal_realm(((
LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/timer.c"
, 634, __func__, "Not using persistent file timestamp %s as it is in the future."
, format_timestamp(z, sizeof(z), ft)); })
634 format_timestamp(z, sizeof(z), ft))({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/timer.c"
, 634, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Not using persistent file timestamp %s as it is in the future."
, format_timestamp(z, sizeof(z), ft)) : log_internal_realm(((
LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/timer.c"
, 634, __func__, "Not using persistent file timestamp %s as it is in the future."
, format_timestamp(z, sizeof(z), ft)); })
;
635 }
636
637 } else if (errno(*__errno_location ()) == ENOENT2)
638 /* The timer has never run before,
639 * make sure a stamp file exists.
640 */
641 (void) touch_file(t->stamp_path, true1, USEC_INFINITY((usec_t) -1), UID_INVALID((uid_t) -1), GID_INVALID((gid_t) -1), MODE_INVALID((mode_t) -1));
642 }
643
644 t->result = TIMER_SUCCESS;
645 timer_enter_waiting(t, true1);
646 return 1;
647}
648
649static int timer_stop(Unit *u) {
650 Timer *t = TIMER(u);
651
652 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 652, __PRETTY_FUNCTION__
); } while (0)
;
653 assert(IN_SET(t->state, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__
((unused)) char _static_assert__macros_need_to_be_extended[20
- sizeof((int[]){TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED
})/sizeof(int)]; switch(t->state) { case TIMER_WAITING: case
TIMER_RUNNING: case TIMER_ELAPSED: _found = 1; break; default
: break; } _found; }))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("IN_SET(t->state, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED)"
), "../src/core/timer.c", 653, __PRETTY_FUNCTION__); } while (
0)
;
654
655 timer_enter_dead(t, TIMER_SUCCESS);
656 return 1;
657}
658
659static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
660 Timer *t = TIMER(u);
661
662 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 662, __PRETTY_FUNCTION__
); } while (0)
;
663 assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("f"), "../src/core/timer.c", 663, __PRETTY_FUNCTION__
); } while (0)
;
664 assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fds"), "../src/core/timer.c", 664, __PRETTY_FUNCTION__
); } while (0)
;
665
666 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
667 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
668
669 if (t->last_trigger.realtime > 0)
670 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64"l" "u", t->last_trigger.realtime);
671
672 if (t->last_trigger.monotonic > 0)
673 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64"l" "u", t->last_trigger.monotonic);
674
675 return 0;
676}
677
678static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
679 Timer *t = TIMER(u);
680 int r;
681
682 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 682, __PRETTY_FUNCTION__
); } while (0)
;
683 assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("key"), "../src/core/timer.c", 683, __PRETTY_FUNCTION__
); } while (0)
;
684 assert(value)do { if ((__builtin_expect(!!(!(value)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("value"), "../src/core/timer.c", 684, __PRETTY_FUNCTION__
); } while (0)
;
685 assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fds"), "../src/core/timer.c", 685, __PRETTY_FUNCTION__
); } while (0)
;
686
687 if (streq(key, "state")(strcmp((key),("state")) == 0)) {
688 TimerState state;
689
690 state = timer_state_from_string(value);
691 if (state < 0)
692 log_unit_debug(u, "Failed to parse state value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/timer.c"
, 692, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse state value: %s", value) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 692, __func__, "Failed to parse state value: %s", value); }
)
;
693 else
694 t->deserialized_state = state;
695 } else if (streq(key, "result")(strcmp((key),("result")) == 0)) {
696 TimerResult f;
697
698 f = timer_result_from_string(value);
699 if (f < 0)
700 log_unit_debug(u, "Failed to parse result value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/timer.c"
, 700, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse result value: %s", value) : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 700, __func__, "Failed to parse result value: %s", value); }
)
;
701 else if (f != TIMER_SUCCESS)
702 t->result = f;
703 } else if (streq(key, "last-trigger-realtime")(strcmp((key),("last-trigger-realtime")) == 0)) {
704
705 r = safe_atou64(value, &t->last_trigger.realtime);
706 if (r < 0)
707 log_unit_debug(u, "Failed to parse last-trigger-realtime value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/timer.c"
, 707, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse last-trigger-realtime value: %s", value) :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7)))
, 0, "../src/core/timer.c", 707, __func__, "Failed to parse last-trigger-realtime value: %s"
, value); })
;
708
709 } else if (streq(key, "last-trigger-monotonic")(strcmp((key),("last-trigger-monotonic")) == 0)) {
710
711 r = safe_atou64(value, &t->last_trigger.monotonic);
712 if (r < 0)
713 log_unit_debug(u, "Failed to parse last-trigger-monotonic value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/timer.c"
, 713, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Failed to parse last-trigger-monotonic value: %s", value) :
log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7)))
, 0, "../src/core/timer.c", 713, __func__, "Failed to parse last-trigger-monotonic value: %s"
, value); })
;
714
715 } else
716 log_unit_debug(u, "Unknown serialization key: %s", key)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/timer.c"
, 716, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Unknown serialization key: %s", key) : log_internal_realm(
((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 716, __func__, "Unknown serialization key: %s", key); })
;
717
718 return 0;
719}
720
721_pure___attribute__ ((pure)) static UnitActiveState timer_active_state(Unit *u) {
722 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 722, __PRETTY_FUNCTION__
); } while (0)
;
723
724 return state_translation_table[TIMER(u)->state];
725}
726
727_pure___attribute__ ((pure)) static const char *timer_sub_state_to_string(Unit *u) {
728 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 728, __PRETTY_FUNCTION__
); } while (0)
;
729
730 return timer_state_to_string(TIMER(u)->state);
731}
732
733static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
734 Timer *t = TIMER(userdata);
735
736 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 736, __PRETTY_FUNCTION__
); } while (0)
;
737
738 if (t->state != TIMER_WAITING)
739 return 0;
740
741 log_unit_debug(UNIT(t), "Timer elapsed.")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(7, 0, "../src/core/timer.c", 741, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Timer elapsed.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 741, __func__, "Timer elapsed."); })
;
742 timer_enter_running(t);
743 return 0;
744}
745
746static void timer_trigger_notify(Unit *u, Unit *other) {
747 Timer *t = TIMER(u);
748 TimerValue *v;
749
750 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 750, __PRETTY_FUNCTION__
); } while (0)
;
751 assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("other"), "../src/core/timer.c", 751, __PRETTY_FUNCTION__
); } while (0)
;
752
753 if (other->load_state != UNIT_LOADED)
754 return;
755
756 /* Reenable all timers that depend on unit state */
757 LIST_FOREACH(value, v, t->values)for ((v) = (t->values); (v); (v) = (v)->value_next)
758 if (IN_SET(v->base, TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE})
/sizeof(int)]; switch(v->base) { case TIMER_UNIT_ACTIVE: case
TIMER_UNIT_INACTIVE: _found = 1; break; default: break; } _found
; })
)
759 v->disabled = false0;
760
761 switch (t->state) {
762
763 case TIMER_WAITING:
764 case TIMER_ELAPSED:
765
766 /* Recalculate sleep time */
767 timer_enter_waiting(t, false0);
768 break;
769
770 case TIMER_RUNNING:
771
772 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
773 log_unit_debug(UNIT(t), "Got notified about unit deactivation.")({ const Unit *_u = (({ typeof(t) _u_ = (t); Unit *_w_ = _u_ ?
&(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal
(7, 0, "../src/core/timer.c", 773, __func__, _u->manager->
unit_log_field, _u->id, _u->manager->invocation_log_field
, _u->invocation_id_string, "Got notified about unit deactivation."
) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7
))), 0, "../src/core/timer.c", 773, __func__, "Got notified about unit deactivation."
); })
;
774 timer_enter_waiting(t, false0);
775 }
776 break;
777
778 case TIMER_DEAD:
779 case TIMER_FAILED:
780 break;
781
782 default:
783 assert_not_reached("Unknown timer state")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unknown timer state"), "../src/core/timer.c", 783, __PRETTY_FUNCTION__
); } while (0)
;
784 }
785}
786
787static void timer_reset_failed(Unit *u) {
788 Timer *t = TIMER(u);
789
790 assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t"), "../src/core/timer.c", 790, __PRETTY_FUNCTION__
); } while (0)
;
791
792 if (t->state == TIMER_FAILED)
793 timer_set_state(t, TIMER_DEAD);
794
795 t->result = TIMER_SUCCESS;
796}
797
798static void timer_time_change(Unit *u) {
799 Timer *t = TIMER(u);
800 usec_t ts;
801
802 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 802, __PRETTY_FUNCTION__
); } while (0)
;
803
804 if (t->state != TIMER_WAITING)
805 return;
806
807 /* If we appear to have triggered in the future, the system clock must
808 * have been set backwards. So let's rewind our own clock and allow
809 * the future trigger(s) to happen again :). Exactly the same as when
810 * you start a timer unit with Persistent=yes. */
811 ts = now(CLOCK_REALTIME0);
812 if (t->last_trigger.realtime > ts)
813 t->last_trigger.realtime = ts;
814
815 log_unit_debug(u, "Time change, recalculating next elapse.")({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/timer.c"
, 815, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Time change, recalculating next elapse.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 815, __func__, "Time change, recalculating next elapse."); }
)
;
816 timer_enter_waiting(t, false0);
817}
818
819static void timer_timezone_change(Unit *u) {
820 Timer *t = TIMER(u);
821
822 assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("u"), "../src/core/timer.c", 822, __PRETTY_FUNCTION__
); } while (0)
;
823
824 if (t->state != TIMER_WAITING)
825 return;
826
827 log_unit_debug(u, "Timezone change, recalculating next elapse.")({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/timer.c"
, 827, __func__, _u->manager->unit_log_field, _u->id
, _u->manager->invocation_log_field, _u->invocation_id_string
, "Timezone change, recalculating next elapse.") : log_internal_realm
(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/timer.c"
, 827, __func__, "Timezone change, recalculating next elapse."
); })
;
828 timer_enter_waiting(t, false0);
829}
830
831static const char* const timer_base_table[_TIMER_BASE_MAX] = {
832 [TIMER_ACTIVE] = "OnActiveSec",
833 [TIMER_BOOT] = "OnBootSec",
834 [TIMER_STARTUP] = "OnStartupSec",
835 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
836 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
837 [TIMER_CALENDAR] = "OnCalendar"
838};
839
840DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase)const char *timer_base_to_string(TimerBase i) { if (i < 0 ||
i >= (TimerBase) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(timer_base_table), typeof(&*(timer_base_table))),
sizeof(timer_base_table)/sizeof((timer_base_table)[0]), ((void
)0)))) return ((void*)0); return timer_base_table[i]; } TimerBase
timer_base_from_string(const char *s) { return (TimerBase) string_table_lookup
(timer_base_table, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(timer_base_table), typeof(&*(timer_base_table))),
sizeof(timer_base_table)/sizeof((timer_base_table)[0]), ((void
)0))), s); }
;
841
842static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
843 [TIMER_SUCCESS] = "success",
844 [TIMER_FAILURE_RESOURCES] = "resources",
845 [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
846};
847
848DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult)const char *timer_result_to_string(TimerResult i) { if (i <
0 || i >= (TimerResult) __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(timer_result_table), typeof
(&*(timer_result_table))), sizeof(timer_result_table)/sizeof
((timer_result_table)[0]), ((void)0)))) return ((void*)0); return
timer_result_table[i]; } TimerResult timer_result_from_string
(const char *s) { return (TimerResult) string_table_lookup(timer_result_table
, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(timer_result_table), typeof(&*(timer_result_table
))), sizeof(timer_result_table)/sizeof((timer_result_table)[0
]), ((void)0))), s); }
;
849
850const UnitVTable timer_vtable = {
851 .object_size = sizeof(Timer),
852
853 .sections =
854 "Unit\0"
855 "Timer\0"
856 "Install\0",
857 .private_section = "Timer",
858
859 .init = timer_init,
860 .done = timer_done,
861 .load = timer_load,
862
863 .coldplug = timer_coldplug,
864
865 .dump = timer_dump,
866
867 .start = timer_start,
868 .stop = timer_stop,
869
870 .serialize = timer_serialize,
871 .deserialize_item = timer_deserialize_item,
872
873 .active_state = timer_active_state,
874 .sub_state_to_string = timer_sub_state_to_string,
875
876 .trigger_notify = timer_trigger_notify,
877
878 .reset_failed = timer_reset_failed,
879 .time_change = timer_time_change,
880 .timezone_change = timer_timezone_change,
881
882 .bus_vtable = bus_timer_vtable,
883 .bus_set_property = bus_timer_set_property,
884
885 .can_transient = true1,
886};