1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
28 #include "load-fragment.h"
30 #include "dbus-scope.h"
32 #include "unit-name.h"
33 #include "load-dropin.h"
35 static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
36 [SCOPE_DEAD] = UNIT_INACTIVE,
37 [SCOPE_RUNNING] = UNIT_ACTIVE,
38 [SCOPE_ABANDONED] = UNIT_ACTIVE,
39 [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
40 [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
41 [SCOPE_FAILED] = UNIT_FAILED
44 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
46 static void scope_init(Unit *u) {
50 assert(u->load_state == UNIT_STUB);
52 s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
54 UNIT(s)->ignore_on_isolate = true;
55 UNIT(s)->ignore_on_snapshot = true;
58 static void scope_done(Unit *u) {
65 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
68 static int scope_arm_timer(Scope *s) {
73 if (s->timeout_stop_usec <= 0) {
74 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
78 if (s->timer_event_source) {
79 r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
83 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
86 return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s);
89 static void scope_set_state(Scope *s, ScopeState state) {
96 if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
97 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
99 if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
100 unit_unwatch_all_pids(UNIT(s));
102 if (state != old_state)
103 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
105 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
108 static int scope_add_default_dependencies(Scope *s) {
113 /* Make sure scopes are unloaded on shutdown */
114 r = unit_add_two_dependencies_by_name(
116 UNIT_BEFORE, UNIT_CONFLICTS,
117 SPECIAL_SHUTDOWN_TARGET, NULL, true);
124 static int scope_verify(Scope *s) {
127 if (UNIT(s)->load_state != UNIT_LOADED)
130 if (set_isempty(UNIT(s)->pids) && UNIT(s)->manager->n_reloading <= 0) {
131 log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
138 static int scope_load(Unit *u) {
143 assert(u->load_state == UNIT_STUB);
145 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
148 u->load_state = UNIT_LOADED;
150 r = unit_load_dropin(u);
154 r = unit_patch_contexts(u);
158 r = unit_add_default_slice(u, &s->cgroup_context);
162 if (u->default_dependencies) {
163 r = scope_add_default_dependencies(s);
168 return scope_verify(s);
171 static int scope_coldplug(Unit *u) {
176 assert(s->state == SCOPE_DEAD);
178 if (s->deserialized_state != s->state) {
180 if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
181 r = scope_arm_timer(s);
186 if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
187 unit_watch_all_pids(UNIT(s));
189 scope_set_state(s, s->deserialized_state);
195 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
202 "%sScope State: %s\n"
204 prefix, scope_state_to_string(s->state),
205 prefix, scope_result_to_string(s->result));
207 cgroup_context_dump(&s->cgroup_context, f, prefix);
208 kill_context_dump(&s->kill_context, f, prefix);
211 static void scope_enter_dead(Scope *s, ScopeResult f) {
214 if (f != SCOPE_SUCCESS)
217 scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
220 static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
221 bool skip_signal = false;
226 if (f != SCOPE_SUCCESS)
229 unit_watch_all_pids(UNIT(s));
231 /* If we have a controller set let's ask the controller nicely
232 * to terminate the scope, instead of us going directly into
233 * SIGTERM beserk mode */
234 if (state == SCOPE_STOP_SIGTERM)
235 skip_signal = bus_scope_send_request_stop(s) > 0;
238 r = unit_kill_context(
241 state != SCOPE_STOP_SIGTERM,
249 r = scope_arm_timer(s);
253 scope_set_state(s, state);
254 } else if (state == SCOPE_STOP_SIGTERM)
255 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
257 scope_enter_dead(s, SCOPE_SUCCESS);
262 log_warning_unit(UNIT(s)->id,
263 "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
265 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
268 static int scope_start(Unit *u) {
274 if (s->state == SCOPE_FAILED)
277 if (s->state == SCOPE_STOP_SIGTERM ||
278 s->state == SCOPE_STOP_SIGKILL)
281 assert(s->state == SCOPE_DEAD);
283 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
286 r = unit_realize_cgroup(u);
288 log_error("Failed to realize cgroup: %s", strerror(-r));
292 r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, UNIT(s)->pids);
296 s->result = SCOPE_SUCCESS;
298 scope_set_state(s, SCOPE_RUNNING);
302 static int scope_stop(Unit *u) {
307 if (s->state == SCOPE_STOP_SIGTERM ||
308 s->state == SCOPE_STOP_SIGKILL)
311 assert(s->state == SCOPE_RUNNING ||
312 s->state == SCOPE_ABANDONED);
314 scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
318 static void scope_reset_failed(Unit *u) {
323 if (s->state == SCOPE_FAILED)
324 scope_set_state(s, SCOPE_DEAD);
326 s->result = SCOPE_SUCCESS;
329 static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
330 return unit_kill_common(u, who, signo, -1, -1, error);
333 static int scope_get_timeout(Unit *u, uint64_t *timeout) {
337 if (!s->timer_event_source)
340 r = sd_event_source_get_time(s->timer_event_source, timeout);
347 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
354 unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
358 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
366 if (streq(key, "state")) {
369 state = scope_state_from_string(value);
371 log_debug("Failed to parse state value %s", value);
373 s->deserialized_state = state;
376 log_debug("Unknown serialization key '%s'", key);
381 static bool scope_check_gc(Unit *u) {
387 /* Never clean up scopes that still have a process around,
388 * even if the scope is formally dead. */
390 if (u->cgroup_path) {
391 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
399 static void scope_notify_cgroup_empty_event(Unit *u) {
403 log_debug_unit(u->id, "%s: cgroup is empty", u->id);
405 if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
406 scope_enter_dead(s, SCOPE_SUCCESS);
409 static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
411 /* If we get a SIGCHLD event for one of the processes we were
412 interested in, then we look for others to watch, under the
413 assumption that we'll sooner or later get a SIGCHLD for
414 them, as the original process we watched was probably the
415 parent of them, and they are hence now our children. */
417 unit_tidy_watch_pids(u, 0, 0);
418 unit_watch_all_pids(u);
420 /* If the PID set is empty now, then let's finish this off */
421 if (set_isempty(u->pids))
422 scope_notify_cgroup_empty_event(u);
425 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
426 Scope *s = SCOPE(userdata);
429 assert(s->timer_event_source == source);
433 case SCOPE_STOP_SIGTERM:
434 if (s->kill_context.send_sigkill) {
435 log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
436 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
438 log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
439 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
444 case SCOPE_STOP_SIGKILL:
445 log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
446 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
450 assert_not_reached("Timeout at wrong time.");
456 int scope_abandon(Scope *s) {
459 if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
463 s->controller = NULL;
465 /* The client is no longer watching the remaining processes,
466 * so let's step in here, under the assumption that the
467 * remaining processes will be sooner or later reassigned to
470 unit_tidy_watch_pids(UNIT(s), 0, 0);
471 unit_watch_all_pids(UNIT(s));
473 /* If the PID set is empty now, then let's finish this off */
474 if (set_isempty(UNIT(s)->pids))
475 scope_notify_cgroup_empty_event(UNIT(s));
477 scope_set_state(s, SCOPE_ABANDONED);
482 _pure_ static UnitActiveState scope_active_state(Unit *u) {
485 return state_translation_table[SCOPE(u)->state];
488 _pure_ static const char *scope_sub_state_to_string(Unit *u) {
491 return scope_state_to_string(SCOPE(u)->state);
494 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
495 [SCOPE_DEAD] = "dead",
496 [SCOPE_RUNNING] = "running",
497 [SCOPE_ABANDONED] = "abandoned",
498 [SCOPE_STOP_SIGTERM] = "stop-sigterm",
499 [SCOPE_STOP_SIGKILL] = "stop-sigkill",
500 [SCOPE_FAILED] = "failed",
503 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
505 static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
506 [SCOPE_SUCCESS] = "success",
507 [SCOPE_FAILURE_RESOURCES] = "resources",
508 [SCOPE_FAILURE_TIMEOUT] = "timeout",
511 DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
513 const UnitVTable scope_vtable = {
514 .object_size = sizeof(Scope),
515 .cgroup_context_offset = offsetof(Scope, cgroup_context),
516 .kill_context_offset = offsetof(Scope, kill_context),
522 .private_section = "Scope",
525 .no_instances = true,
531 .coldplug = scope_coldplug,
535 .start = scope_start,
540 .get_timeout = scope_get_timeout,
542 .serialize = scope_serialize,
543 .deserialize_item = scope_deserialize_item,
545 .active_state = scope_active_state,
546 .sub_state_to_string = scope_sub_state_to_string,
548 .check_gc = scope_check_gc,
550 .sigchld_event = scope_sigchld_event,
552 .reset_failed = scope_reset_failed,
554 .notify_cgroup_empty = scope_notify_cgroup_empty_event,
556 .bus_interface = "org.freedesktop.systemd1.Scope",
557 .bus_vtable = bus_scope_vtable,
558 .bus_set_property = bus_scope_set_property,
559 .bus_commit_properties = bus_scope_commit_properties,
561 .can_transient = true