scope.c revision 13b84ec7df103ce388910a2b868fe1668c1e27ef
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen/***
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen This file is part of systemd.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Copyright 2013 Lennart Poettering
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen systemd is free software; you can redistribute it and/or modify it
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen under the terms of the GNU Lesser General Public License as published by
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen the Free Software Foundation; either version 2.1 of the License, or
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen (at your option) any later version.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen systemd is distributed in the hope that it will be useful, but
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen WITHOUT ANY WARRANTY; without even the implied warranty of
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Lesser General Public License for more details.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen You should have received a copy of the GNU Lesser General Public License
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen along with systemd; If not, see <http://www.gnu.org/licenses/>.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen***/
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <errno.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <signal.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <unistd.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "unit.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "scope.h"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include "load-fragment.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "log.h"
a09561746f15b84da9471b5c4be74e53d19e4f3fLennart Poettering#include "dbus-scope.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "special.h"
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok#include "unit-name.h"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include "load-dropin.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poetteringstatic const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering [SCOPE_DEAD] = UNIT_INACTIVE,
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering [SCOPE_RUNNING] = UNIT_ACTIVE,
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski [SCOPE_FAILED] = UNIT_FAILED
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho};
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chenstatic void scope_init(Unit *u) {
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Scope *s = SCOPE(u);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen assert(u);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek assert(u->load_state == UNIT_STUB);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho watch_init(&s->timer_watch);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho cgroup_context_init(&s->cgroup_context);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho kill_context_init(&s->kill_context);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho UNIT(s)->ignore_on_isolate = true;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho UNIT(s)->ignore_on_snapshot = true;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek}
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekstatic void scope_done(Unit *u) {
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Scope *s = SCOPE(u);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(u);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen cgroup_context_done(&s->cgroup_context);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho set_free(s->pids);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek s->pids = NULL;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen unit_unwatch_timer(u, &s->timer_watch);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen}
fea7838e7e0b2724f5e0bc028121a08b42995045Zbigniew Jędrzejewski-Szmek
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chenstatic void scope_set_state(Scope *s, ScopeState state) {
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen ScopeState old_state;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek assert(s);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen old_state = s->state;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho s->state = state;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (state != SCOPE_STOP_SIGTERM &&
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek state != SCOPE_STOP_SIGKILL)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek unit_unwatch_timer(UNIT(s), &s->timer_watch);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (state != old_state)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho log_debug("%s changed %s -> %s",
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen UNIT(s)->id,
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen scope_state_to_string(old_state),
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen scope_state_to_string(state));
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek}
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poetteringstatic int scope_add_default_dependencies(Scope *s) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho int r;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen assert(s);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen /* Make sure scopes are unloaded on shutdown */
fea7838e7e0b2724f5e0bc028121a08b42995045Zbigniew Jędrzejewski-Szmek r = unit_add_two_dependencies_by_name(
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho UNIT(s),
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho UNIT_BEFORE, UNIT_CONFLICTS,
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho SPECIAL_SHUTDOWN_TARGET, NULL, true);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (r < 0)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return r;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return 0;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho}
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chostatic int scope_verify(Scope *s) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(s);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (UNIT(s)->load_state != UNIT_LOADED)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return 0;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (set_size(s->pids) <= 0 && UNIT(s)->manager->n_reloading <= 0) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_error_unit(UNIT(s)->id, "Scope %s has no PIDs. Refusing.", UNIT(s)->id);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return -EINVAL;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho }
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return 0;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho}
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chostatic int scope_load(Unit *u) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho Scope *s = SCOPE(u);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho int r;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(s);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(u->load_state == UNIT_STUB);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return -ENOENT;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho u->load_state = UNIT_LOADED;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho r = unit_load_dropin(u);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (r < 0)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return r;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho r = unit_add_default_slice(u);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (r < 0)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return r;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (u->default_dependencies) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho r = scope_add_default_dependencies(s);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (r < 0)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return r;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho }
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return scope_verify(s);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho}
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chostatic int scope_coldplug(Unit *u) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho Scope *s = SCOPE(u);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho int r;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(s);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(s->state == SCOPE_DEAD);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (s->deserialized_state != s->state) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if ((s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho && s->timeout_stop_usec > 0) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho if (r < 0)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return r;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho }
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho scope_set_state(s, s->deserialized_state);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho }
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho return 0;
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho}
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chostatic void scope_dump(Unit *u, FILE *f, const char *prefix) {
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho Scope *s = SCOPE(u);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(s);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(f);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho fprintf(f,
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho "%sScope State: %s\n"
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho "%sResult: %s\n",
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho prefix, scope_state_to_string(s->state),
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho prefix, scope_result_to_string(s->result));
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek cgroup_context_dump(&s->cgroup_context, f, prefix);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho kill_context_dump(&s->kill_context, f, prefix);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho}
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekstatic void scope_enter_dead(Scope *s, ScopeResult f) {
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen assert(s);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen if (f != SCOPE_SUCCESS)
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho s->result = f;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler}
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schauflerstatic void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler int r;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler assert(s);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (f != SCOPE_SUCCESS)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler s->result = f;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler r = unit_kill_context(
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler UNIT(s),
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler &s->kill_context,
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler state != SCOPE_STOP_SIGTERM,
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler -1, -1, false);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (r < 0)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler goto fail;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (r > 0) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (s->timeout_stop_usec > 0) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (r < 0)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler goto fail;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler }
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler scope_set_state(s, state);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler } else
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler scope_enter_dead(s, SCOPE_SUCCESS);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schauflerfail:
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler log_warning_unit(UNIT(s)->id,
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler}
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schauflerstatic int scope_start(Unit *u) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler Scope *s = SCOPE(u);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler int r;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler assert(s);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (s->state == SCOPE_FAILED)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return -EPERM;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (s->state == SCOPE_STOP_SIGTERM ||
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler s->state == SCOPE_STOP_SIGKILL)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return -EAGAIN;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler assert(s->state == SCOPE_DEAD);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return -ENOENT;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler r = unit_realize_cgroup(u);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (r < 0) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler log_error("Failed to realize cgroup: %s", strerror(-r));
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return r;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler }
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, s->pids);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (r < 0)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return r;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler set_free(s->pids);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler s->pids = NULL;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski s->result = SCOPE_SUCCESS;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
8a188de9e0ea41509beda12084126d7a75ebe86eWaLyong Cho scope_set_state(s, SCOPE_RUNNING);
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski return 0;
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski}
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekstatic int scope_stop(Unit *u) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek Scope *s = SCOPE(u);
e49d3c016751c03e544697656e8e596af8a664d7Łukasz Stelmach
e49d3c016751c03e544697656e8e596af8a664d7Łukasz Stelmach assert(s);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(s->state == SCOPE_RUNNING);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (s->state == SCOPE_STOP_SIGTERM ||
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek s->state == SCOPE_STOP_SIGKILL)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return 0;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(s->state == SCOPE_RUNNING);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return 0;
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen}
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poetteringstatic void scope_reset_failed(Unit *u) {
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen Scope *s = SCOPE(u);
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen assert(s);
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok
4c1fc3e404d648c70bd2f50ac50aeac6ece8872eDaniel Mack if (s->state == SCOPE_FAILED)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler scope_set_state(s, SCOPE_DEAD);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler s->result = SCOPE_SUCCESS;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler}
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schauflerstatic int scope_kill(Unit *u, KillWho who, int signo, DBusError *error) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return unit_kill_common(u, who, signo, -1, -1, error);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler}
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schauflerstatic int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler Scope *s = SCOPE(u);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok assert(s);
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok assert(f);
6656aefb42385b468dd96867118d049f945cbf81WaLyong Cho assert(fds);
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen return 0;
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen}
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen
6656aefb42385b468dd96867118d049f945cbf81WaLyong Chostatic int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler Scope *s = SCOPE(u);
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen
abbacb1defaaecb8d2477685f7bb3fabcf58585bNathaniel Chen assert(u);
b9289d4c6e13ec5fb67bfce69c826d93b004da6aPhilippe De Swert assert(key);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek assert(value);
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering assert(fds);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (streq(key, "state")) {
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler ScopeState state;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler state = scope_state_from_string(value);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler if (state < 0)
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler log_debug("Failed to parse state value %s", value);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek else
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler s->deserialized_state = state;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler } else
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler log_debug("Unknown serialization key '%s'", key);
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler return 0;
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler}
ae176752f9c91073d234448b28ae95b37b97b719Casey Schaufler
ae176752f9c91073d234448b28ae95b37b97b719Casey Schauflerstatic bool scope_check_gc(Unit *u) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek Scope *s = SCOPE(u);
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski int r;
e49d3c016751c03e544697656e8e596af8a664d7Łukasz Stelmach
e49d3c016751c03e544697656e8e596af8a664d7Łukasz Stelmach assert(s);
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski /* Never clean up scopes that still have a process around,
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski * even if the scope is formally dead. */
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
if (UNIT(s)->cgroup_path) {
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true);
if (r <= 0)
return true;
}
return false;
}
static void scope_timer_event(Unit *u, uint64_t elapsed, Watch*w) {
Scope *s = SCOPE(u);
assert(s);
assert(elapsed == 1);
assert(w == &s->timer_watch);
switch (s->state) {
case SCOPE_STOP_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(u->id, "%s stopping timed out. Killing.", u->id);
scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
} else {
log_warning_unit(u->id, "%s stopping timed out. Skipping SIGKILL.", u->id);
scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
}
break;
case SCOPE_STOP_SIGKILL:
log_warning_unit(u->id, "%s still around after SIGKILL. Ignoring.", u->id);
scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
break;
default:
assert_not_reached("Timeout at wrong time.");
}
}
static void scope_notify_cgroup_empty_event(Unit *u) {
Scope *s = SCOPE(u);
assert(u);
log_debug_unit(u->id, "%s: cgroup is empty", u->id);
switch (s->state) {
case SCOPE_RUNNING:
case SCOPE_STOP_SIGTERM:
case SCOPE_STOP_SIGKILL:
scope_enter_dead(s, SCOPE_SUCCESS);
break;
default:
;
}
}
_pure_ static UnitActiveState scope_active_state(Unit *u) {
assert(u);
return state_translation_table[SCOPE(u)->state];
}
_pure_ static const char *scope_sub_state_to_string(Unit *u) {
assert(u);
return scope_state_to_string(SCOPE(u)->state);
}
static const char* const scope_state_table[_SCOPE_STATE_MAX] = {
[SCOPE_DEAD] = "dead",
[SCOPE_RUNNING] = "running",
[SCOPE_STOP_SIGTERM] = "stop-sigterm",
[SCOPE_STOP_SIGKILL] = "stop-sigkill",
[SCOPE_FAILED] = "failed",
};
DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState);
static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
[SCOPE_SUCCESS] = "success",
[SCOPE_FAILURE_RESOURCES] = "resources",
[SCOPE_FAILURE_TIMEOUT] = "timeout",
};
DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
const UnitVTable scope_vtable = {
.object_size = sizeof(Scope),
.sections =
"Unit\0"
"Scope\0"
"Install\0",
.private_section = "Scope",
.cgroup_context_offset = offsetof(Scope, cgroup_context),
.no_alias = true,
.no_instances = true,
.init = scope_init,
.load = scope_load,
.done = scope_done,
.coldplug = scope_coldplug,
.dump = scope_dump,
.start = scope_start,
.stop = scope_stop,
.kill = scope_kill,
.serialize = scope_serialize,
.deserialize_item = scope_deserialize_item,
.active_state = scope_active_state,
.sub_state_to_string = scope_sub_state_to_string,
.check_gc = scope_check_gc,
.timer_event = scope_timer_event,
.reset_failed = scope_reset_failed,
.notify_cgroup_empty = scope_notify_cgroup_empty_event,
.bus_interface = "org.freedesktop.systemd1.Scope",
.bus_message_handler = bus_scope_message_handler,
.bus_set_property = bus_scope_set_property,
.bus_commit_properties = bus_scope_commit_properties,
.can_transient = true
};