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_STOP_SIGTERM] = UNIT_DEACTIVATING,
39 [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
40 [SCOPE_FAILED] = UNIT_FAILED
43 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
45 static void scope_init(Unit *u) {
49 assert(u->load_state == UNIT_STUB);
51 s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
53 cgroup_context_init(&s->cgroup_context);
54 kill_context_init(&s->kill_context);
56 UNIT(s)->ignore_on_isolate = true;
57 UNIT(s)->ignore_on_snapshot = true;
60 static void scope_done(Unit *u) {
65 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, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s, &s->timer_event_source);
96 static void scope_set_state(Scope *s, ScopeState state) {
100 old_state = s->state;
103 if (state != SCOPE_STOP_SIGTERM &&
104 state != SCOPE_STOP_SIGKILL)
105 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
107 if (state != old_state)
108 log_debug("%s changed %s -> %s",
110 scope_state_to_string(old_state),
111 scope_state_to_string(state));
113 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
116 static int scope_add_default_dependencies(Scope *s) {
121 /* Make sure scopes are unloaded on shutdown */
122 r = unit_add_two_dependencies_by_name(
124 UNIT_BEFORE, UNIT_CONFLICTS,
125 SPECIAL_SHUTDOWN_TARGET, NULL, true);
132 static int scope_verify(Scope *s) {
135 if (UNIT(s)->load_state != UNIT_LOADED)
138 if (set_size(s->pids) <= 0 && UNIT(s)->manager->n_reloading <= 0) {
139 log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
146 static int scope_load(Unit *u) {
151 assert(u->load_state == UNIT_STUB);
153 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
156 u->load_state = UNIT_LOADED;
158 r = unit_load_dropin(u);
162 r = unit_add_default_slice(u);
166 if (u->default_dependencies) {
167 r = scope_add_default_dependencies(s);
172 return scope_verify(s);
175 static int scope_coldplug(Unit *u) {
180 assert(s->state == SCOPE_DEAD);
182 if (s->deserialized_state != s->state) {
184 if (s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM) {
185 r = scope_arm_timer(s);
190 scope_set_state(s, s->deserialized_state);
196 static void scope_dump(Unit *u, FILE *f, const char *prefix) {
203 "%sScope State: %s\n"
205 prefix, scope_state_to_string(s->state),
206 prefix, scope_result_to_string(s->result));
208 cgroup_context_dump(&s->cgroup_context, f, prefix);
209 kill_context_dump(&s->kill_context, f, prefix);
212 static void scope_enter_dead(Scope *s, ScopeResult f) {
215 if (f != SCOPE_SUCCESS)
218 scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
221 static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
222 bool skip_signal = false;
227 if (f != SCOPE_SUCCESS)
230 /* If we have a controller set let's ask the controller nicely
231 * to terminate the scope, instead of us going directly into
232 * SIGTERM beserk mode */
233 if (state == SCOPE_STOP_SIGTERM)
234 skip_signal = bus_scope_send_request_stop(s) > 0;
237 r = unit_kill_context(
240 state != SCOPE_STOP_SIGTERM,
248 r = scope_arm_timer(s);
252 scope_set_state(s, state);
253 } else if (state == SCOPE_STOP_SIGTERM)
254 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
256 scope_enter_dead(s, SCOPE_SUCCESS);
261 log_warning_unit(UNIT(s)->id,
262 "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
264 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
267 static int scope_start(Unit *u) {
273 if (s->state == SCOPE_FAILED)
276 if (s->state == SCOPE_STOP_SIGTERM ||
277 s->state == SCOPE_STOP_SIGKILL)
280 assert(s->state == SCOPE_DEAD);
282 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
285 r = unit_realize_cgroup(u);
287 log_error("Failed to realize cgroup: %s", strerror(-r));
291 r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids);
298 s->result = SCOPE_SUCCESS;
300 scope_set_state(s, SCOPE_RUNNING);
304 static int scope_stop(Unit *u) {
308 assert(s->state == SCOPE_RUNNING);
310 if (s->state == SCOPE_STOP_SIGTERM ||
311 s->state == SCOPE_STOP_SIGKILL)
314 assert(s->state == SCOPE_RUNNING);
316 scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
320 static void scope_reset_failed(Unit *u) {
325 if (s->state == SCOPE_FAILED)
326 scope_set_state(s, SCOPE_DEAD);
328 s->result = SCOPE_SUCCESS;
331 static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
332 return unit_kill_common(u, who, signo, -1, -1, error);
335 static int scope_get_timeout(Unit *u, uint64_t *timeout) {
339 if (!s->timer_event_source)
342 r = sd_event_source_get_time(s->timer_event_source, timeout);
349 static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
356 unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
360 static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
368 if (streq(key, "state")) {
371 state = scope_state_from_string(value);
373 log_debug("Failed to parse state value %s", value);
375 s->deserialized_state = state;
378 log_debug("Unknown serialization key '%s'", key);
383 static bool scope_check_gc(Unit *u) {
389 /* Never clean up scopes that still have a process around,
390 * even if the scope is formally dead. */
392 if (UNIT(s)->cgroup_path) {
393 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
401 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
402 Scope *s = SCOPE(userdata);
405 assert(s->timer_event_source == source);
409 case SCOPE_STOP_SIGTERM:
410 if (s->kill_context.send_sigkill) {
411 log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
412 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
414 log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
415 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
420 case SCOPE_STOP_SIGKILL:
421 log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
422 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
426 assert_not_reached("Timeout at wrong time.");
432 static void scope_notify_cgroup_empty_event(Unit *u) {
436 log_debug_unit(u->id, "%s: cgroup is empty", u->id);
441 case SCOPE_STOP_SIGTERM:
442 case SCOPE_STOP_SIGKILL:
443 scope_enter_dead(s, SCOPE_SUCCESS);
452 _pure_ static UnitActiveState scope_active_state(Unit *u) {
455 return state_translation_table[SCOPE(u)->state];
458 _pure_ static const char *scope_sub_state_to_string(Unit *u) {
461 return scope_state_to_string(SCOPE(u)->state);
464 static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
465 [SCOPE_DEAD] = "dead",
466 [SCOPE_RUNNING] = "running",
467 [SCOPE_STOP_SIGTERM] = "stop-sigterm",
468 [SCOPE_STOP_SIGKILL] = "stop-sigkill",
469 [SCOPE_FAILED] = "failed",
472 DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
474 static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
475 [SCOPE_SUCCESS] = "success",
476 [SCOPE_FAILURE_RESOURCES] = "resources",
477 [SCOPE_FAILURE_TIMEOUT] = "timeout",
480 DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
482 const UnitVTable scope_vtable = {
483 .object_size = sizeof(Scope),
484 .cgroup_context_offset = offsetof(Scope, cgroup_context),
485 .kill_context_offset = offsetof(Scope, kill_context),
491 .private_section = "Scope",
494 .no_instances = true,
500 .coldplug = scope_coldplug,
504 .start = scope_start,
509 .get_timeout = scope_get_timeout,
511 .serialize = scope_serialize,
512 .deserialize_item = scope_deserialize_item,
514 .active_state = scope_active_state,
515 .sub_state_to_string = scope_sub_state_to_string,
517 .check_gc = scope_check_gc,
519 .reset_failed = scope_reset_failed,
521 .notify_cgroup_empty = scope_notify_cgroup_empty_event,
523 .bus_interface = "org.freedesktop.systemd1.Scope",
524 .bus_vtable = bus_scope_vtable,
525 .bus_set_property = bus_scope_set_property,
526 .bus_commit_properties = bus_scope_commit_properties,
528 .can_transient = true