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 cgroup_context_init(&s->cgroup_context);
55 kill_context_init(&s->kill_context);
57 unit_cgroup_context_init_defaults(u, &s->cgroup_context);
59 UNIT(s)->ignore_on_isolate = true;
60 UNIT(s)->ignore_on_snapshot = true;
63 static void scope_done(Unit *u) {
68 cgroup_context_done(&s->cgroup_context);
72 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
75 static int scope_arm_timer(Scope *s) {
80 if (s->timeout_stop_usec <= 0) {
81 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
85 if (s->timer_event_source) {
86 r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
90 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
93 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);
96 static void scope_set_state(Scope *s, ScopeState state) {
100 old_state = s->state;
103 if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
104 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
106 if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED))
107 unit_unwatch_all_pids(UNIT(s));
109 if (state != old_state)
110 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
112 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
115 static int scope_add_default_dependencies(Scope *s) {
120 /* Make sure scopes are unloaded on shutdown */
121 r = unit_add_two_dependencies_by_name(
123 UNIT_BEFORE, UNIT_CONFLICTS,
124 SPECIAL_SHUTDOWN_TARGET, NULL, true);
131 static int scope_verify(Scope *s) {
134 if (UNIT(s)->load_state != UNIT_LOADED)
137 if (set_isempty(UNIT(s)->pids) && UNIT(s)->manager->n_reloading <= 0) {
138 log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
145 static int scope_load(Unit *u) {
150 assert(u->load_state == UNIT_STUB);
152 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
155 u->load_state = UNIT_LOADED;
157 r = unit_load_dropin(u);
161 r = unit_add_default_slice(u);
165 if (u->default_dependencies) {
166 r = scope_add_default_dependencies(s);
171 return scope_verify(s);
174 static int scope_coldplug(Unit *u) {
179 assert(s->state == SCOPE_DEAD);
181 if (s->deserialized_state != s->state) {
183 if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
184 r = scope_arm_timer(s);
189 if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
190 unit_watch_all_pids(UNIT(s));
192 scope_set_state(s, s->deserialized_state);
198 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
205 "%sScope State: %s\n"
207 prefix, scope_state_to_string(s->state),
208 prefix, scope_result_to_string(s->result));
210 cgroup_context_dump(&s->cgroup_context, f, prefix);
211 kill_context_dump(&s->kill_context, f, prefix);
214 static void scope_enter_dead(Scope *s, ScopeResult f) {
217 if (f != SCOPE_SUCCESS)
220 scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
223 static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
224 bool skip_signal = false;
229 if (f != SCOPE_SUCCESS)
232 unit_watch_all_pids(UNIT(s));
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;
241 r = unit_kill_context(
244 state != SCOPE_STOP_SIGTERM,
252 r = scope_arm_timer(s);
256 scope_set_state(s, state);
257 } else if (state == SCOPE_STOP_SIGTERM)
258 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
260 scope_enter_dead(s, SCOPE_SUCCESS);
265 log_warning_unit(UNIT(s)->id,
266 "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
268 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
271 static int scope_start(Unit *u) {
277 if (s->state == SCOPE_FAILED)
280 if (s->state == SCOPE_STOP_SIGTERM ||
281 s->state == SCOPE_STOP_SIGKILL)
284 assert(s->state == SCOPE_DEAD);
286 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
289 r = unit_realize_cgroup(u);
291 log_error("Failed to realize cgroup: %s", strerror(-r));
295 r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, UNIT(s)->pids);
299 s->result = SCOPE_SUCCESS;
301 scope_set_state(s, SCOPE_RUNNING);
305 static int scope_stop(Unit *u) {
310 if (s->state == SCOPE_STOP_SIGTERM ||
311 s->state == SCOPE_STOP_SIGKILL)
314 assert(s->state == SCOPE_RUNNING ||
315 s->state == SCOPE_ABANDONED);
317 scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
321 static void scope_reset_failed(Unit *u) {
326 if (s->state == SCOPE_FAILED)
327 scope_set_state(s, SCOPE_DEAD);
329 s->result = SCOPE_SUCCESS;
332 static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
333 return unit_kill_common(u, who, signo, -1, -1, error);
336 static int scope_get_timeout(Unit *u, uint64_t *timeout) {
340 if (!s->timer_event_source)
343 r = sd_event_source_get_time(s->timer_event_source, timeout);
350 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
357 unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
361 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
369 if (streq(key, "state")) {
372 state = scope_state_from_string(value);
374 log_debug("Failed to parse state value %s", value);
376 s->deserialized_state = state;
379 log_debug("Unknown serialization key '%s'", key);
384 static bool scope_check_gc(Unit *u) {
390 /* Never clean up scopes that still have a process around,
391 * even if the scope is formally dead. */
393 if (u->cgroup_path) {
394 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
402 static void scope_notify_cgroup_empty_event(Unit *u) {
406 log_debug_unit(u->id, "%s: cgroup is empty", u->id);
408 if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
409 scope_enter_dead(s, SCOPE_SUCCESS);
412 static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
414 /* If we get a SIGCHLD event for one of the processes we were
415 interested in, then we look for others to watch, under the
416 assumption that we'll sooner or later get a SIGCHLD for
417 them, as the original process we watched was probably the
418 parent of them, and they are hence now our children. */
420 unit_tidy_watch_pids(u, 0, 0);
421 unit_watch_all_pids(u);
423 /* If the PID set is empty now, then let's finish this off */
424 if (set_isempty(u->pids))
425 scope_notify_cgroup_empty_event(u);
428 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
429 Scope *s = SCOPE(userdata);
432 assert(s->timer_event_source == source);
436 case SCOPE_STOP_SIGTERM:
437 if (s->kill_context.send_sigkill) {
438 log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
439 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
441 log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
442 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
447 case SCOPE_STOP_SIGKILL:
448 log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
449 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
453 assert_not_reached("Timeout at wrong time.");
459 int scope_abandon(Scope *s) {
462 if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
466 s->controller = NULL;
468 /* The client is no longer watching the remaining processes,
469 * so let's step in here, under the assumption that the
470 * remaining processes will be sooner or later reassigned to
473 unit_tidy_watch_pids(UNIT(s), 0, 0);
474 unit_watch_all_pids(UNIT(s));
476 /* If the PID set is empty now, then let's finish this off */
477 if (set_isempty(UNIT(s)->pids))
478 scope_notify_cgroup_empty_event(UNIT(s));
480 scope_set_state(s, SCOPE_ABANDONED);
485 _pure_ static UnitActiveState scope_active_state(Unit *u) {
488 return state_translation_table[SCOPE(u)->state];
491 _pure_ static const char *scope_sub_state_to_string(Unit *u) {
494 return scope_state_to_string(SCOPE(u)->state);
497 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
498 [SCOPE_DEAD] = "dead",
499 [SCOPE_RUNNING] = "running",
500 [SCOPE_ABANDONED] = "abandoned",
501 [SCOPE_STOP_SIGTERM] = "stop-sigterm",
502 [SCOPE_STOP_SIGKILL] = "stop-sigkill",
503 [SCOPE_FAILED] = "failed",
506 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
508 static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
509 [SCOPE_SUCCESS] = "success",
510 [SCOPE_FAILURE_RESOURCES] = "resources",
511 [SCOPE_FAILURE_TIMEOUT] = "timeout",
514 DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
516 const UnitVTable scope_vtable = {
517 .object_size = sizeof(Scope),
518 .cgroup_context_offset = offsetof(Scope, cgroup_context),
519 .kill_context_offset = offsetof(Scope, kill_context),
525 .private_section = "Scope",
528 .no_instances = true,
534 .coldplug = scope_coldplug,
538 .start = scope_start,
543 .get_timeout = scope_get_timeout,
545 .serialize = scope_serialize,
546 .deserialize_item = scope_deserialize_item,
548 .active_state = scope_active_state,
549 .sub_state_to_string = scope_sub_state_to_string,
551 .check_gc = scope_check_gc,
553 .sigchld_event = scope_sigchld_event,
555 .reset_failed = scope_reset_failed,
557 .notify_cgroup_empty = scope_notify_cgroup_empty_event,
559 .bus_interface = "org.freedesktop.systemd1.Scope",
560 .bus_vtable = bus_scope_vtable,
561 .bus_set_property = bus_scope_set_property,
562 .bus_commit_properties = bus_scope_commit_properties,
564 .can_transient = true