]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/scope.c
bus-util: print correct warnings for units that fail but for which we have a NULL...
[thirdparty/systemd.git] / src / core / scope.c
CommitLineData
6c12b52e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
6c12b52e
LP
23#include <unistd.h>
24
25#include "unit.h"
26#include "scope.h"
6c12b52e
LP
27#include "log.h"
28#include "dbus-scope.h"
29#include "special.h"
30#include "unit-name.h"
31#include "load-dropin.h"
32
33static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
34 [SCOPE_DEAD] = UNIT_INACTIVE,
35 [SCOPE_RUNNING] = UNIT_ACTIVE,
a911bb9a 36 [SCOPE_ABANDONED] = UNIT_ACTIVE,
6c12b52e
LP
37 [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
38 [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
39 [SCOPE_FAILED] = UNIT_FAILED
40};
41
718db961
LP
42static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
43
6c12b52e
LP
44static void scope_init(Unit *u) {
45 Scope *s = SCOPE(u);
46
47 assert(u);
48 assert(u->load_state == UNIT_STUB);
49
1f19a534 50 s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
6c12b52e 51
6c12b52e
LP
52 UNIT(s)->ignore_on_isolate = true;
53 UNIT(s)->ignore_on_snapshot = true;
54}
55
56static void scope_done(Unit *u) {
57 Scope *s = SCOPE(u);
58
59 assert(u);
60
2d4a39e7
LP
61 free(s->controller);
62
718db961
LP
63 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
64}
65
66static int scope_arm_timer(Scope *s) {
67 int r;
68
69 assert(s);
70
71 if (s->timeout_stop_usec <= 0) {
72 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
73 return 0;
74 }
75
76 if (s->timer_event_source) {
77 r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
78 if (r < 0)
79 return r;
80
81 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
82 }
83
6a0f1f6d
LP
84 return sd_event_add_time(
85 UNIT(s)->manager->event,
86 &s->timer_event_source,
87 CLOCK_MONOTONIC,
88 now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0,
89 scope_dispatch_timer, s);
6c12b52e
LP
90}
91
92static void scope_set_state(Scope *s, ScopeState state) {
93 ScopeState old_state;
94 assert(s);
95
96 old_state = s->state;
97 s->state = state;
98
a911bb9a 99 if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
718db961 100 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
6c12b52e 101
a911bb9a
LP
102 if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
103 unit_unwatch_all_pids(UNIT(s));
104
6c12b52e 105 if (state != old_state)
a911bb9a 106 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
6c12b52e
LP
107
108 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
109}
110
111static int scope_add_default_dependencies(Scope *s) {
112 int r;
113
114 assert(s);
115
116 /* Make sure scopes are unloaded on shutdown */
117 r = unit_add_two_dependencies_by_name(
118 UNIT(s),
119 UNIT_BEFORE, UNIT_CONFLICTS,
120 SPECIAL_SHUTDOWN_TARGET, NULL, true);
121 if (r < 0)
122 return r;
123
124 return 0;
125}
126
127static int scope_verify(Scope *s) {
128 assert(s);
129
130 if (UNIT(s)->load_state != UNIT_LOADED)
131 return 0;
132
a911bb9a 133 if (set_isempty(UNIT(s)->pids) && UNIT(s)->manager->n_reloading <= 0) {
79008bdd 134 log_unit_error(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
6c12b52e
LP
135 return -EINVAL;
136 }
137
138 return 0;
139}
140
141static int scope_load(Unit *u) {
142 Scope *s = SCOPE(u);
143 int r;
144
145 assert(s);
146 assert(u->load_state == UNIT_STUB);
147
148 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
149 return -ENOENT;
150
151 u->load_state = UNIT_LOADED;
152
153 r = unit_load_dropin(u);
154 if (r < 0)
155 return r;
156
598459ce
LP
157 r = unit_patch_contexts(u);
158 if (r < 0)
159 return r;
160
161 r = unit_add_default_slice(u, &s->cgroup_context);
6c12b52e
LP
162 if (r < 0)
163 return r;
164
165 if (u->default_dependencies) {
166 r = scope_add_default_dependencies(s);
167 if (r < 0)
168 return r;
169 }
170
171 return scope_verify(s);
172}
173
be847e82 174static int scope_coldplug(Unit *u) {
6c12b52e
LP
175 Scope *s = SCOPE(u);
176 int r;
177
178 assert(s);
179 assert(s->state == SCOPE_DEAD);
180
181 if (s->deserialized_state != s->state) {
182
a911bb9a 183 if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
718db961 184 r = scope_arm_timer(s);
6c12b52e 185 if (r < 0)
6c12b52e
LP
186 return r;
187 }
188
a911bb9a
LP
189 if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
190 unit_watch_all_pids(UNIT(s));
191
6c12b52e
LP
192 scope_set_state(s, s->deserialized_state);
193 }
194
195 return 0;
196}
197
198static void scope_dump(Unit *u, FILE *f, const char *prefix) {
199 Scope *s = SCOPE(u);
200
201 assert(s);
202 assert(f);
203
204 fprintf(f,
205 "%sScope State: %s\n"
206 "%sResult: %s\n",
207 prefix, scope_state_to_string(s->state),
208 prefix, scope_result_to_string(s->result));
209
210 cgroup_context_dump(&s->cgroup_context, f, prefix);
211 kill_context_dump(&s->kill_context, f, prefix);
212}
213
214static void scope_enter_dead(Scope *s, ScopeResult f) {
215 assert(s);
216
217 if (f != SCOPE_SUCCESS)
218 s->result = f;
219
220 scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
221}
222
223static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
2d4a39e7 224 bool skip_signal = false;
6c12b52e
LP
225 int r;
226
227 assert(s);
228
229 if (f != SCOPE_SUCCESS)
230 s->result = f;
231
a911bb9a
LP
232 unit_watch_all_pids(UNIT(s));
233
2d4a39e7
LP
234 /* If we have a controller set let's ask the controller nicely
235 * to terminate the scope, instead of us going directly into
236 * SIGTERM beserk mode */
237 if (state == SCOPE_STOP_SIGTERM)
238 skip_signal = bus_scope_send_request_stop(s) > 0;
239
240 if (!skip_signal) {
241 r = unit_kill_context(
242 UNIT(s),
243 &s->kill_context,
db2cb23b 244 state != SCOPE_STOP_SIGTERM ? KILL_KILL : KILL_TERMINATE,
2d4a39e7
LP
245 -1, -1, false);
246 if (r < 0)
247 goto fail;
248 } else
249 r = 1;
6c12b52e
LP
250
251 if (r > 0) {
718db961
LP
252 r = scope_arm_timer(s);
253 if (r < 0)
254 goto fail;
6c12b52e
LP
255
256 scope_set_state(s, state);
ac84d1fb
LP
257 } else if (state == SCOPE_STOP_SIGTERM)
258 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
259 else
6c12b52e
LP
260 scope_enter_dead(s, SCOPE_SUCCESS);
261
262 return;
263
264fail:
79008bdd 265 log_unit_warning(UNIT(s)->id,
6c12b52e
LP
266 "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
267
268 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
269}
270
271static int scope_start(Unit *u) {
272 Scope *s = SCOPE(u);
273 int r;
274
275 assert(s);
276
7b617155
LP
277 if (s->state == SCOPE_FAILED)
278 return -EPERM;
279
6c12b52e
LP
280 if (s->state == SCOPE_STOP_SIGTERM ||
281 s->state == SCOPE_STOP_SIGKILL)
282 return -EAGAIN;
283
284 assert(s->state == SCOPE_DEAD);
285
286 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
287 return -ENOENT;
288
5ad096b3
LP
289 (void) unit_realize_cgroup(u);
290 (void) unit_reset_cpu_usage(u);
291
7b3fd631 292 r = unit_attach_pids_to_cgroup(u);
6c12b52e
LP
293 if (r < 0)
294 return r;
295
6c12b52e
LP
296 s->result = SCOPE_SUCCESS;
297
298 scope_set_state(s, SCOPE_RUNNING);
82a2b6bb 299 return 1;
6c12b52e
LP
300}
301
302static int scope_stop(Unit *u) {
303 Scope *s = SCOPE(u);
304
305 assert(s);
6c12b52e
LP
306
307 if (s->state == SCOPE_STOP_SIGTERM ||
308 s->state == SCOPE_STOP_SIGKILL)
309 return 0;
310
a911bb9a
LP
311 assert(s->state == SCOPE_RUNNING ||
312 s->state == SCOPE_ABANDONED);
6c12b52e
LP
313
314 scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
82a2b6bb 315 return 1;
6c12b52e
LP
316}
317
8bcca7e2
LP
318static void scope_reset_failed(Unit *u) {
319 Scope *s = SCOPE(u);
320
321 assert(s);
322
323 if (s->state == SCOPE_FAILED)
324 scope_set_state(s, SCOPE_DEAD);
325
326 s->result = SCOPE_SUCCESS;
327}
328
718db961 329static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
6c12b52e
LP
330 return unit_kill_common(u, who, signo, -1, -1, error);
331}
332
68db7a3b
ZJS
333static int scope_get_timeout(Unit *u, uint64_t *timeout) {
334 Scope *s = SCOPE(u);
335 int r;
336
337 if (!s->timer_event_source)
338 return 0;
339
340 r = sd_event_source_get_time(s->timer_event_source, timeout);
341 if (r < 0)
342 return r;
343
344 return 1;
345}
346
6c12b52e
LP
347static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
348 Scope *s = SCOPE(u);
349
350 assert(s);
351 assert(f);
352 assert(fds);
353
354 unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
355 return 0;
356}
357
358static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
359 Scope *s = SCOPE(u);
360
361 assert(u);
362 assert(key);
363 assert(value);
364 assert(fds);
365
366 if (streq(key, "state")) {
367 ScopeState state;
368
369 state = scope_state_from_string(value);
370 if (state < 0)
371 log_debug("Failed to parse state value %s", value);
372 else
373 s->deserialized_state = state;
374
375 } else
376 log_debug("Unknown serialization key '%s'", key);
377
378 return 0;
379}
380
381static bool scope_check_gc(Unit *u) {
4e2744fc 382 assert(u);
6c12b52e
LP
383
384 /* Never clean up scopes that still have a process around,
385 * even if the scope is formally dead. */
386
a911bb9a 387 if (u->cgroup_path) {
4e2744fc
RC
388 int r;
389
a911bb9a 390 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
6c12b52e
LP
391 if (r <= 0)
392 return true;
393 }
394
395 return false;
396}
397
a911bb9a
LP
398static void scope_notify_cgroup_empty_event(Unit *u) {
399 Scope *s = SCOPE(u);
400 assert(u);
401
79008bdd 402 log_unit_debug(u->id, "%s: cgroup is empty", u->id);
a911bb9a
LP
403
404 if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
405 scope_enter_dead(s, SCOPE_SUCCESS);
406}
407
408static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
409
410 /* If we get a SIGCHLD event for one of the processes we were
411 interested in, then we look for others to watch, under the
412 assumption that we'll sooner or later get a SIGCHLD for
413 them, as the original process we watched was probably the
414 parent of them, and they are hence now our children. */
415
416 unit_tidy_watch_pids(u, 0, 0);
417 unit_watch_all_pids(u);
418
419 /* If the PID set is empty now, then let's finish this off */
420 if (set_isempty(u->pids))
421 scope_notify_cgroup_empty_event(u);
422}
423
718db961
LP
424static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
425 Scope *s = SCOPE(userdata);
6c12b52e
LP
426
427 assert(s);
718db961 428 assert(s->timer_event_source == source);
6c12b52e
LP
429
430 switch (s->state) {
431
432 case SCOPE_STOP_SIGTERM:
433 if (s->kill_context.send_sigkill) {
79008bdd 434 log_unit_warning(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
6c12b52e
LP
435 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
436 } else {
79008bdd 437 log_unit_warning(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
6c12b52e
LP
438 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
439 }
440
441 break;
442
443 case SCOPE_STOP_SIGKILL:
79008bdd 444 log_unit_warning(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
6c12b52e
LP
445 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
446 break;
447
448 default:
449 assert_not_reached("Timeout at wrong time.");
450 }
718db961
LP
451
452 return 0;
6c12b52e
LP
453}
454
a911bb9a
LP
455int scope_abandon(Scope *s) {
456 assert(s);
6c12b52e 457
a911bb9a
LP
458 if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
459 return -ESTALE;
6c12b52e 460
a911bb9a
LP
461 free(s->controller);
462 s->controller = NULL;
6c12b52e 463
a911bb9a
LP
464 /* The client is no longer watching the remaining processes,
465 * so let's step in here, under the assumption that the
466 * remaining processes will be sooner or later reassigned to
467 * us as parent. */
6c12b52e 468
a911bb9a
LP
469 unit_tidy_watch_pids(UNIT(s), 0, 0);
470 unit_watch_all_pids(UNIT(s));
6c12b52e 471
a911bb9a
LP
472 /* If the PID set is empty now, then let's finish this off */
473 if (set_isempty(UNIT(s)->pids))
474 scope_notify_cgroup_empty_event(UNIT(s));
475 else
476 scope_set_state(s, SCOPE_ABANDONED);
477
478 return 0;
6c12b52e
LP
479}
480
481_pure_ static UnitActiveState scope_active_state(Unit *u) {
482 assert(u);
483
484 return state_translation_table[SCOPE(u)->state];
485}
486
487_pure_ static const char *scope_sub_state_to_string(Unit *u) {
488 assert(u);
489
490 return scope_state_to_string(SCOPE(u)->state);
491}
492
493static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
494 [SCOPE_DEAD] = "dead",
358712f3 495 [SCOPE_RUNNING] = "running",
a911bb9a 496 [SCOPE_ABANDONED] = "abandoned",
6c12b52e
LP
497 [SCOPE_STOP_SIGTERM] = "stop-sigterm",
498 [SCOPE_STOP_SIGKILL] = "stop-sigkill",
499 [SCOPE_FAILED] = "failed",
500};
501
502DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
503
504static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
505 [SCOPE_SUCCESS] = "success",
506 [SCOPE_FAILURE_RESOURCES] = "resources",
507 [SCOPE_FAILURE_TIMEOUT] = "timeout",
508};
509
510DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
511
512const UnitVTable scope_vtable = {
513 .object_size = sizeof(Scope),
718db961
LP
514 .cgroup_context_offset = offsetof(Scope, cgroup_context),
515 .kill_context_offset = offsetof(Scope, kill_context),
516
6c12b52e
LP
517 .sections =
518 "Unit\0"
519 "Scope\0"
520 "Install\0",
6c12b52e 521 .private_section = "Scope",
6c12b52e
LP
522
523 .no_alias = true,
524 .no_instances = true,
525
526 .init = scope_init,
527 .load = scope_load,
528 .done = scope_done,
529
530 .coldplug = scope_coldplug,
531
532 .dump = scope_dump,
533
534 .start = scope_start,
535 .stop = scope_stop,
536
537 .kill = scope_kill,
538
68db7a3b
ZJS
539 .get_timeout = scope_get_timeout,
540
6c12b52e
LP
541 .serialize = scope_serialize,
542 .deserialize_item = scope_deserialize_item,
543
544 .active_state = scope_active_state,
545 .sub_state_to_string = scope_sub_state_to_string,
546
547 .check_gc = scope_check_gc,
548
a911bb9a
LP
549 .sigchld_event = scope_sigchld_event,
550
8bcca7e2
LP
551 .reset_failed = scope_reset_failed,
552
6c12b52e
LP
553 .notify_cgroup_empty = scope_notify_cgroup_empty_event,
554
555 .bus_interface = "org.freedesktop.systemd1.Scope",
718db961 556 .bus_vtable = bus_scope_vtable,
6c12b52e
LP
557 .bus_set_property = bus_scope_set_property,
558 .bus_commit_properties = bus_scope_commit_properties,
559
560 .can_transient = true
561};