From bb2c7685454842549bc1fe47adc35cbca2a84190 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Jan 2018 19:54:26 +0100 Subject: [PATCH] core: add a new unit_needs_console() call This call determines whether a specific unit currently needs access to the console. It's a fancy wrapper around exec_context_may_touch_console() ultimately, however for service units we'll explicitly exclude the SERVICE_EXITED state from when we report true. --- src/core/service.c | 27 +++++++++++++++++++++++++++ src/core/unit.c | 22 ++++++++++++++++++++++ src/core/unit.h | 5 +++++ 3 files changed, 54 insertions(+) diff --git a/src/core/service.c b/src/core/service.c index 81c776c..425e2a1 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3806,6 +3806,32 @@ static int service_control_pid(Unit *u) { return s->control_pid; } +static bool service_needs_console(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + /* We provide our own implementation of this here, instead of relying of the generic implementation + * unit_needs_console() provides, since we want to return false if we are in SERVICE_EXITED state. */ + + if (!exec_context_may_touch_console(&s->exec_context)) + return false; + + return IN_SET(s->state, + SERVICE_START_PRE, + SERVICE_START, + SERVICE_START_POST, + SERVICE_RUNNING, + SERVICE_RELOAD, + SERVICE_STOP, + SERVICE_STOP_SIGABRT, + SERVICE_STOP_SIGTERM, + SERVICE_STOP_SIGKILL, + SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, + SERVICE_FINAL_SIGKILL); +} + static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { [SERVICE_RESTART_NO] = "no", [SERVICE_RESTART_ON_SUCCESS] = "on-success", @@ -3921,6 +3947,7 @@ const UnitVTable service_vtable = { .bus_commit_properties = bus_service_commit_properties, .get_timeout = service_get_timeout, + .needs_console = service_needs_console, .can_transient = true, .status_message_formats = { diff --git a/src/core/unit.c b/src/core/unit.c index 97585a7..4081db8 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5350,6 +5350,28 @@ void unit_warn_leftover_processes(Unit *u) { (void) cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_leftover, u); } +bool unit_needs_console(Unit *u) { + ExecContext *ec; + UnitActiveState state; + + assert(u); + + state = unit_active_state(u); + + if (UNIT_IS_INACTIVE_OR_FAILED(state)) + return false; + + if (UNIT_VTABLE(u)->needs_console) + return UNIT_VTABLE(u)->needs_console(u); + + /* If this unit type doesn't implement this call, let's use a generic fallback implementation: */ + ec = unit_get_exec_context(u); + if (!ec) + return false; + + return exec_context_may_touch_console(ec); +} + static const char* const collect_mode_table[_COLLECT_MODE_MAX] = { [COLLECT_INACTIVE] = "inactive", [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed", diff --git a/src/core/unit.h b/src/core/unit.h index 4cd0706..ec171ad 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -541,6 +541,9 @@ struct UnitVTable { /* Returns the main PID if there is any defined, or 0. */ pid_t (*control_pid)(Unit *u); + /* Returns true if the unit currently needs access to the console */ + bool (*needs_console)(Unit *u); + /* This is called for each unit type and should be used to * enumerate existing devices and load them. However, * everything that is loaded here should still stay in @@ -795,6 +798,8 @@ int unit_prepare_exec(Unit *u); void unit_warn_leftover_processes(Unit *u); +bool unit_needs_console(Unit *u); + /* Macros which append UNIT= or USER_UNIT= to the message */ #define log_unit_full(unit, level, error, ...) \ -- 2.7.4