File: | build-scan/../src/core/timer.c |
Warning: | line 49, column 17 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
21 | static 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 | ||||
29 | static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata); | |||
30 | ||||
31 | static 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 | ||||
43 | void 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); | |||
47 | ||||
48 | while ((v = t->values)) { | |||
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); | |||
| ||||
50 | calendar_spec_free(v->calendar_spec); | |||
51 | free(v); | |||
52 | } | |||
53 | } | |||
54 | ||||
55 | static 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); | |||
| ||||
59 | ||||
60 | timer_free_values(t); | |||
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 | ||||
68 | static 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 | ||||
82 | static 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 | ||||
113 | static 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 | ||||
129 | static 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 | ||||
168 | static 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 | ||||
197 | static 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 | ||||
245 | static 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 | ||||
265 | static void timer_enter_waiting(Timer *t, bool_Bool initial); | |||
266 | ||||
267 | static 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 | ||||
284 | static 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 | ||||
298 | static 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 | ||||
315 | static 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 | ||||
337 | static 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 | ||||
546 | fail: | |||
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 | ||||
551 | static 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 | ||||
581 | fail: | |||
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 | ||||
586 | static 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 | ||||
649 | static 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 | ||||
659 | static 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 | ||||
678 | static 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 | ||||
733 | static 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 | ||||
746 | static 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 | ||||
787 | static 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 | ||||
798 | static 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 | ||||
819 | static 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 | ||||
831 | static 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 | ||||
840 | DEFINE_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 | ||||
842 | static 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 | ||||
848 | DEFINE_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 | ||||
850 | const 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 | }; |