From f03ec2b180425d01dc9867556683dcb82fac4b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 10:38:19 +0200 Subject: [PATCH 01/13] systemctl: fix typo --- src/systemctl/systemctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index be1b7375af..cc5b1a9ea0 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -8449,7 +8449,7 @@ static int start_with_fallback(void) { static int halt_now(enum action a) { /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be - * synce'd explicitly in advance. */ + * synced explicitly in advance. */ if (!arg_no_sync && !arg_dry_run) (void) sync(); From 1bcf3fc6c57d92927b96cad8c739099b4ceae236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 17 Oct 2018 17:48:35 +0200 Subject: [PATCH 02/13] core: return true from cg_is_empty* on ENOENT --- src/basic/cgroup-util.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 7728b63a5f..b725a17761 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1166,7 +1166,7 @@ int cg_is_empty(const char *controller, const char *path) { r = cg_enumerate_processes(controller, path, &f); if (r == -ENOENT) - return 1; + return true; if (r < 0) return r; @@ -1196,6 +1196,8 @@ int cg_is_empty_recursive(const char *controller, const char *path) { * via the "populated" attribute of "cgroup.events". */ r = cg_read_event(controller, path, "populated", &t); + if (r == -ENOENT) + return true; if (r < 0) return r; @@ -1210,7 +1212,7 @@ int cg_is_empty_recursive(const char *controller, const char *path) { r = cg_enumerate_subgroups(controller, path, &d); if (r == -ENOENT) - return 1; + return true; if (r < 0) return r; From ef5ae8e71329e43c277e6d4f983f0c0793047b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 22:45:34 +0200 Subject: [PATCH 03/13] core: consider service with no start command immediately started The service would always be in state == SERVICE_INACTIVE, but it needs to go through state == SERVICE_START so that SuccessAction/FailureAction are executed. --- src/core/service.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/service.c b/src/core/service.c index 3d065bf487..5472e1a908 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2024,6 +2024,12 @@ static void service_enter_start(Service *s) { goto fail; } + /* We force a fake state transition here. Otherwise, the unit would go directly from + * SERVICE_DEAD to SERVICE_DEAD without SERVICE_ACTIVATING or SERVICE_ACTIVE + * inbetween. This way we can later trigger actions that depend on the state + * transition, including SuccessAction=. */ + service_set_state(s, SERVICE_START); + service_enter_start_post(s); return; } From 454dd6ce7adb744584ecae9aa0bd1acf3a00e9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 15:56:35 +0200 Subject: [PATCH 04/13] man: move description of *Action= modes to FailureAction=/SuccessAction= FailureAction=/SuccessAction= were added later then StartLimitAction=, so it was easiest to refer to the existing description. But those two settings are somewhat simpler (they just execute the action unconditionally) while StartLimitAction= has additional timing and burst parameters, and they are about to take on a more prominent role, so let's move the description of allowed values. --- man/systemd.unit.xml | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index f418f5b5ee..4574da13a9 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -864,6 +864,24 @@ + + FailureAction= + SuccessAction= + + Configure the action to take when the unit stops and enters a failed state or inactive + state. Takes one of , , , + , , or + . If is set, no action will be triggered. + causes a reboot following the normal shutdown procedure (i.e. equivalent to + systemctl reboot). causes a forced reboot which will + terminate all processes forcibly but should cause no dirty file systems on reboot (i.e. equivalent to + systemctl reboot -f) and causes immediate execution of the + reboot2 system call, which + might result in data loss. Similarly, , , + have the effect of powering down the system with similar semantics. Both + options default to . + + JobTimeoutSec= JobRunningTimeoutSec= @@ -920,29 +938,13 @@ StartLimitAction= - Configure the action to take if the rate limit configured with - StartLimitIntervalSec= and StartLimitBurst= is hit. Takes one of - , , , - , , or - . If is set, hitting the rate limit will trigger no - action besides that the start will not be permitted. causes a reboot following the - normal shutdown procedure (i.e. equivalent to systemctl reboot). - causes a forced reboot which will terminate all processes forcibly but should - cause no dirty file systems on reboot (i.e. equivalent to systemctl reboot -f) and - causes immediate execution of the - reboot2 system call, which - might result in data loss. Similarly, , , - have the effect of powering down the system with similar - semantics. Defaults to . + Configure an additional action to take if the rate limit configured with + StartLimitIntervalSec= and StartLimitBurst= is hit. Takes the same + values as the setting FailureAction=/SuccessAction= settings and executes + the same actions. If is set, hitting the rate limit will trigger no action besides that + the start will not be permitted. Defaults to . - - FailureAction= - SuccessAction= - Configure the action to take when the unit stops and enters a failed state or inactive - state. Takes the same values as the setting StartLimitAction= setting and executes the same - actions. Both options default to . - RebootArgument= From 54fcb6192c618726d11404b24b1a1e9ec3169ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 13:28:39 +0200 Subject: [PATCH 05/13] core: define "exit" and "exit-force" actions for user units and only accept that We would accept e.g. FailureAction=reboot-force in user units and then do an exit in the user manager. Let's be stricter, and define "exit"/"exit-force" as the only supported actions in user units. v2: - rename 'exit' to 'exit-force' and add new 'exit' - add test for the parsing function --- TODO | 4 +++ man/systemd.unit.xml | 26 +++++++++------- src/core/dbus-unit.c | 37 ++++++++++++++++++++++- src/core/emergency-action.c | 47 ++++++++++++++++++++++------- src/core/emergency-action.h | 5 ++++ src/core/load-fragment.c | 42 +++++++++++++++++++++++++- src/test/meson.build | 5 ++++ src/test/test-emergency-action.c | 51 ++++++++++++++++++++++++++++++++ 8 files changed, 195 insertions(+), 22 deletions(-) create mode 100644 src/test/test-emergency-action.c diff --git a/TODO b/TODO index e79aeda90e..db2b61c3e2 100644 --- a/TODO +++ b/TODO @@ -2,6 +2,10 @@ Bugfixes: * copy.c: set the right chattrs before copying files and others after +* Many manager configuration settings that are only applicable to user + manager or system manager can be always set. It would be better to reject + them when parsing config. + External: * Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros. diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 4574da13a9..9f65394b06 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -868,18 +868,24 @@ FailureAction= SuccessAction= - Configure the action to take when the unit stops and enters a failed state or inactive - state. Takes one of , , , - , , or - . If is set, no action will be triggered. - causes a reboot following the normal shutdown procedure (i.e. equivalent to - systemctl reboot). causes a forced reboot which will - terminate all processes forcibly but should cause no dirty file systems on reboot (i.e. equivalent to - systemctl reboot -f) and causes immediate execution of the + Configure the action to take when the unit stops and enters a failed state or inactive state. + Takes one of , , , + , , , + , , and . In system mode, + all options except and are allowed. In user mode, only + , , and are allowed. Both options default + to . + + If is set, no action will be triggered. causes a reboot + following the normal shutdown procedure (i.e. equivalent to systemctl reboot). + causes a forced reboot which will terminate all processes forcibly but should + cause no dirty file systems on reboot (i.e. equivalent to systemctl reboot -f) and + causes immediate execution of the reboot2 system call, which might result in data loss. Similarly, , , - have the effect of powering down the system with similar semantics. Both - options default to . + have the effect of powering down the system with similar + semantics. causes the user manager to exit following the normal shutdown procedure, and + causes it terminate without shutting down services. diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index c4530f0c8b..daec85a73b 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1299,8 +1299,43 @@ static int bus_unit_set_live_property( return 0; } +static int bus_set_transient_emergency_action( + Unit *u, + const char *name, + EmergencyAction *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + const char *s; + EmergencyAction v; + int r; + bool system; + + assert(p); + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + system = MANAGER_IS_SYSTEM(u->manager); + r = parse_emergency_action(s, system, &v); + if (v < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + v == -EOPNOTSUPP ? "EmergencyAction setting invalid for manager type: %s" + : "Invalid %s setting: %s", + name, s); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + *p = v; + unit_write_settingf(u, flags, name, + "%s=%s", name, s); + } + + return 1; +} + static BUS_DEFINE_SET_TRANSIENT_PARSE(collect_mode, CollectMode, collect_mode_from_string); -static BUS_DEFINE_SET_TRANSIENT_PARSE(emergency_action, EmergencyAction, emergency_action_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(job_mode, JobMode, job_mode_from_string); static int bus_set_transient_conditions( diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c index 6f0b0a8f33..e14a3aae17 100644 --- a/src/core/emergency-action.c +++ b/src/core/emergency-action.c @@ -36,15 +36,6 @@ int emergency_action( return -ECANCELED; } - if (!MANAGER_IS_SYSTEM(m)) { - /* Downgrade all options to simply exiting if we run - * in user mode */ - - log_warning("Exiting: %s", reason); - m->objective = MANAGER_EXIT; - return -ECANCELED; - } - switch (action) { case EMERGENCY_ACTION_REBOOT: @@ -78,11 +69,26 @@ int emergency_action( (void) reboot(RB_AUTOBOOT); break; + case EMERGENCY_ACTION_EXIT: + assert(MANAGER_IS_USER(m)); + + log_and_status(m, "Exiting", reason); + + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); + break; + case EMERGENCY_ACTION_POWEROFF: log_and_status(m, "Powering off", reason); (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); break; + case EMERGENCY_ACTION_EXIT_FORCE: + assert(MANAGER_IS_USER(m)); + + log_and_status(m, "Exiting immediately", reason); + m->objective = MANAGER_EXIT; + break; + case EMERGENCY_ACTION_POWEROFF_FORCE: log_and_status(m, "Forcibly powering off", reason); m->objective = MANAGER_POWEROFF; @@ -111,6 +117,27 @@ static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = { [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate", [EMERGENCY_ACTION_POWEROFF] = "poweroff", [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force", - [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate" + [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate", + [EMERGENCY_ACTION_EXIT] = "exit", + [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force", }; DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction); + +int parse_emergency_action( + const char *value, + bool system, + EmergencyAction *ret) { + + EmergencyAction x; + + x = emergency_action_from_string(value); + if (x < 0) + return -EINVAL; + + if ((system && x >= _EMERGENCY_ACTION_FIRST_USER_ACTION) || + (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)) + return -EOPNOTSUPP; + + *ret = x; + return 0; +} diff --git a/src/core/emergency-action.h b/src/core/emergency-action.h index ea6590e78a..3f6f6e0a03 100644 --- a/src/core/emergency-action.h +++ b/src/core/emergency-action.h @@ -9,6 +9,9 @@ typedef enum EmergencyAction { EMERGENCY_ACTION_POWEROFF, EMERGENCY_ACTION_POWEROFF_FORCE, EMERGENCY_ACTION_POWEROFF_IMMEDIATE, + EMERGENCY_ACTION_EXIT, + _EMERGENCY_ACTION_FIRST_USER_ACTION = EMERGENCY_ACTION_EXIT, + EMERGENCY_ACTION_EXIT_FORCE, _EMERGENCY_ACTION_MAX, _EMERGENCY_ACTION_INVALID = -1 } EmergencyAction; @@ -20,3 +23,5 @@ int emergency_action(Manager *m, EmergencyAction action, const char *reboot_arg, const char* emergency_action_to_string(EmergencyAction i) _const_; EmergencyAction emergency_action_from_string(const char *s) _pure_; + +int parse_emergency_action(const char *value, bool system, EmergencyAction *ret); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index f96775ee71..b4299c5882 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -76,7 +76,6 @@ DEFINE_CONFIG_PARSE(config_parse_socket_protocol, supported_socket_protocol_from DEFINE_CONFIG_PARSE(config_parse_exec_secure_bits, secure_bits_from_string, "Failed to parse secure bits"); DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy"); -DEFINE_CONFIG_PARSE_ENUM(config_parse_emergency_action, emergency_action, EmergencyAction, "Failed to parse failure action specifier"); DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode"); @@ -4185,6 +4184,47 @@ int config_parse_job_running_timeout_sec( return 0; } +int config_parse_emergency_action( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Manager *m = NULL; + EmergencyAction *x = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (unit) + m = ((Unit*) userdata)->manager; + else + m = data; + + r = parse_emergency_action(rvalue, MANAGER_IS_SYSTEM(m), x); + if (r < 0) { + if (r == -EOPNOTSUPP) + log_syntax(unit, LOG_ERR, filename, line, r, + "%s= specified as %s mode action, ignoring: %s", + lvalue, MANAGER_IS_SYSTEM(m) ? "user" : "system", rvalue); + else + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse %s=, ignoring: %s", lvalue, rvalue); + return 0; + } + + return 0; +} + #define FOLLOW_MAX 8 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { diff --git a/src/test/meson.build b/src/test/meson.build index 2e003f1fd2..a1770213a8 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -63,6 +63,11 @@ tests += [ libmount, libblkid]], + [['src/test/test-emergency-action.c'], + [libcore, + libshared], + []], + [['src/test/test-job-type.c'], [libcore, libshared], diff --git a/src/test/test-emergency-action.c b/src/test/test-emergency-action.c new file mode 100644 index 0000000000..493b23227e --- /dev/null +++ b/src/test/test-emergency-action.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "emergency-action.h" +#include "tests.h" + +static void test_parse_emergency_action(void) { + EmergencyAction x; + + log_info("/* %s */", __func__); + + assert_se(parse_emergency_action("none", false, &x) == 0); + assert_se(x == EMERGENCY_ACTION_NONE); + assert_se(parse_emergency_action("reboot", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("reboot-force", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("reboot-immediate", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("poweroff", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("poweroff-force", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("poweroff-immediate", false, &x) == -EOPNOTSUPP); + assert_se(x == EMERGENCY_ACTION_NONE); + assert_se(parse_emergency_action("exit", false, &x) == 0); + assert_se(x == EMERGENCY_ACTION_EXIT); + assert_se(parse_emergency_action("exit-force", false, &x) == 0); + assert_se(x == EMERGENCY_ACTION_EXIT_FORCE); + assert_se(parse_emergency_action("exit-forcee", false, &x) == -EINVAL); + + assert_se(parse_emergency_action("none", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_NONE); + assert_se(parse_emergency_action("reboot", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_REBOOT); + assert_se(parse_emergency_action("reboot-force", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_REBOOT_FORCE); + assert_se(parse_emergency_action("reboot-immediate", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_REBOOT_IMMEDIATE); + assert_se(parse_emergency_action("poweroff", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_POWEROFF); + assert_se(parse_emergency_action("poweroff-force", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_POWEROFF_FORCE); + assert_se(parse_emergency_action("poweroff-immediate", true, &x) == 0); + assert_se(parse_emergency_action("exit", true, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("exit-force", true, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("exit-forcee", true, &x) == -EINVAL); + assert_se(x == EMERGENCY_ACTION_POWEROFF_IMMEDIATE); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_INFO); + + test_parse_emergency_action(); + + return EXIT_SUCCESS; +} From 469f76f170db39c72578e869ec7c087bb43f9350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 14:49:36 +0200 Subject: [PATCH 06/13] core: accept system mode emergency action specifiers with a warning Before we would only accept those "system" values, so there wasn't other chocie. Let's provide backwards compatiblity in case somebody made use of this functionality in user mode. v2: use 'exit-force' not 'exit' v3: use error value in log_syntax --- src/core/load-fragment.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index b4299c5882..bfd1d5b15f 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -4212,6 +4212,16 @@ int config_parse_emergency_action( r = parse_emergency_action(rvalue, MANAGER_IS_SYSTEM(m), x); if (r < 0) { + if (r == -EOPNOTSUPP && MANAGER_IS_USER(m)) { + /* Compat mode: remove for systemd 241. */ + + log_syntax(unit, LOG_INFO, filename, line, r, + "%s= in user mode specified as \"%s\", using \"exit-force\" instead.", + lvalue, rvalue); + *x = EMERGENCY_ACTION_EXIT_FORCE; + return 0; + } + if (r == -EOPNOTSUPP) log_syntax(unit, LOG_ERR, filename, line, r, "%s= specified as %s mode action, ignoring: %s", From 3f00d379fa6221a4570c8cd955afd9b661787db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 15:07:42 +0200 Subject: [PATCH 07/13] core: allow services with no commands but SuccessAction set --- src/core/service.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index 5472e1a908..03e6792fec 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -538,8 +538,13 @@ static int service_verify(Service *s) { if (UNIT(s)->load_state != UNIT_LOADED) return 0; - if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) { - log_unit_error(UNIT(s), "Service lacks both ExecStart= and ExecStop= setting. Refusing."); + if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP] + && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) { + /* FailureAction= only makes sense if one of the start or stop commands is specified. + * SuccessAction= will be executed unconditionally if no commands are specified. Hence, + * either a command or SuccessAction= are required. */ + + log_unit_error(UNIT(s), "Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing."); return -ENOEXEC; } @@ -548,8 +553,8 @@ static int service_verify(Service *s) { return -ENOEXEC; } - if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START]) { - log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing."); + if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START] && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) { + log_unit_error(UNIT(s), "Service has no ExecStart= and no SuccessAction= settings and does not have RemainAfterExit=yes set. Refusing."); return -ENOEXEC; } From 1710d4beff6329cf6ae0767953cad09593517b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 15:24:44 +0200 Subject: [PATCH 08/13] core: limit service-watchdogs=no to actual "watchdog" commands The setting is now only looked at when considering an action for a job timeout or unit start limit. It is ignored for ctrl-alt-del, SuccessAction, SuccessFailure. v2: turn the parameter into a flag field v3: rename Options to Flags --- src/core/emergency-action.c | 3 ++- src/core/emergency-action.h | 8 +++++++- src/core/job.c | 3 ++- src/core/manager.c | 2 +- src/core/unit.c | 9 ++++++--- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c index e14a3aae17..3f0c11a3f2 100644 --- a/src/core/emergency-action.c +++ b/src/core/emergency-action.c @@ -21,6 +21,7 @@ static void log_and_status(Manager *m, const char *message, const char *reason) int emergency_action( Manager *m, EmergencyAction action, + EmergencyActionFlags options, const char *reboot_arg, const char *reason) { @@ -31,7 +32,7 @@ int emergency_action( if (action == EMERGENCY_ACTION_NONE) return -ECANCELED; - if (!m->service_watchdogs) { + if (FLAGS_SET(options, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) { log_warning("Watchdog disabled! Not acting on: %s", reason); return -ECANCELED; } diff --git a/src/core/emergency-action.h b/src/core/emergency-action.h index 3f6f6e0a03..453de0dbd2 100644 --- a/src/core/emergency-action.h +++ b/src/core/emergency-action.h @@ -16,10 +16,16 @@ typedef enum EmergencyAction { _EMERGENCY_ACTION_INVALID = -1 } EmergencyAction; +typedef enum EmergencyActionFlags { + EMERGENCY_ACTION_IS_WATCHDOG = 1 << 0, +} EmergencyActionFlags; + #include "macro.h" #include "manager.h" -int emergency_action(Manager *m, EmergencyAction action, const char *reboot_arg, const char *reason); +int emergency_action(Manager *m, + EmergencyAction action, EmergencyActionFlags options, + const char *reboot_arg, const char *reason); const char* emergency_action_to_string(EmergencyAction i) _const_; EmergencyAction emergency_action_from_string(const char *s) _pure_; diff --git a/src/core/job.c b/src/core/job.c index 6b17cc1d6f..23717d5e47 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -973,7 +973,8 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user u = j->unit; job_finish_and_invalidate(j, JOB_TIMEOUT, true, false); - emergency_action(u->manager, u->job_timeout_action, u->job_timeout_reboot_arg, "job timed out"); + emergency_action(u->manager, u->job_timeout_action, EMERGENCY_ACTION_IS_WATCHDOG, + u->job_timeout_reboot_arg, "job timed out"); return 0; } diff --git a/src/core/manager.c b/src/core/manager.c index af84a0a769..0c3109b34b 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2538,7 +2538,7 @@ static void manager_handle_ctrl_alt_del(Manager *m) { if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE) manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); else - emergency_action(m, m->cad_burst_action, NULL, + emergency_action(m, m->cad_burst_action, 0, NULL, "Ctrl-Alt-Del was pressed more than 7 times within 2s"); } diff --git a/src/core/unit.c b/src/core/unit.c index d90456e03c..0806a50cce 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1724,7 +1724,8 @@ int unit_start_limit_test(Unit *u) { log_unit_warning(u, "Start request repeated too quickly."); u->start_limit_hit = true; - return emergency_action(u->manager, u->start_limit_action, u->reboot_arg, "unit failed"); + return emergency_action(u->manager, u->start_limit_action, EMERGENCY_ACTION_IS_WATCHDOG, + u->reboot_arg, "unit failed"); } bool unit_shall_confirm_spawn(Unit *u) { @@ -2498,9 +2499,11 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag unit_check_binds_to(u); if (os != UNIT_FAILED && ns == UNIT_FAILED) - (void) emergency_action(u->manager, u->failure_action, u->reboot_arg, "unit failed"); + (void) emergency_action(u->manager, u->failure_action, 0, + u->reboot_arg, "unit failed"); else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && ns == UNIT_INACTIVE) - (void) emergency_action(u->manager, u->success_action, u->reboot_arg, "unit succeeded"); + (void) emergency_action(u->manager, u->success_action, 0, + u->reboot_arg, "unit succeeded"); } unit_add_to_dbus_queue(u); From 631c9b7bf2dab5065d753a7b1cfaff5b100b3c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 15:09:11 +0200 Subject: [PATCH 09/13] units: use SuccessAction=exit-force in systemd-exit.service Fixes #10414. v2: - rename .service.in to .service - rename 'exit' to 'exit-force' --- units/user/meson.build | 2 +- units/user/{systemd-exit.service.in => systemd-exit.service} | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) rename units/user/{systemd-exit.service.in => systemd-exit.service} (87%) diff --git a/units/user/meson.build b/units/user/meson.build index b1c2e95597..36341a42f5 100644 --- a/units/user/meson.build +++ b/units/user/meson.build @@ -14,6 +14,7 @@ units = [ 'sockets.target', 'sound.target', 'timers.target', + 'systemd-exit.service', 'systemd-tmpfiles-clean.timer', ] @@ -23,7 +24,6 @@ foreach file : units endforeach in_units = [ - 'systemd-exit.service', 'systemd-tmpfiles-clean.service', 'systemd-tmpfiles-setup.service', ] diff --git a/units/user/systemd-exit.service.in b/units/user/systemd-exit.service similarity index 87% rename from units/user/systemd-exit.service.in rename to units/user/systemd-exit.service index d69273f6b3..1d3b61e3ab 100644 --- a/units/user/systemd-exit.service.in +++ b/units/user/systemd-exit.service @@ -13,7 +13,4 @@ Documentation=man:systemd.special(7) DefaultDependencies=no Requires=shutdown.target After=shutdown.target - -[Service] -Type=oneshot -ExecStart=@SYSTEMCTL@ --user --force exit +SuccessAction=exit-force From d85515edcf9700dc068201ab9f7103f04f3b25b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 15:30:53 +0200 Subject: [PATCH 10/13] units: use SuccessAction=reboot-force in systemd-reboot.service --- TODO | 6 ------ units/meson.build | 2 +- units/{systemd-reboot.service.in => systemd-reboot.service} | 5 +---- 3 files changed, 2 insertions(+), 11 deletions(-) rename units/{systemd-reboot.service.in => systemd-reboot.service} (89%) diff --git a/TODO b/TODO index db2b61c3e2..0b6573518f 100644 --- a/TODO +++ b/TODO @@ -44,12 +44,6 @@ Features: * chown() tty a service is attached to after the service goes down -* replace systemd-reboot.service's ExecStart= with a single SuccessAction= - line, so that we don't need to fork() for executing the reboot - service. Similar for other services like this, such as systemd-exit.service - and so on. Of course, for this to work service units with no ExecYYZ= set but - SuccessAction= set need to be acceptable. - * optionally: turn on cgroup delegation for per-session scope units * optionally, if a per-partition GPT flag is set for the root/home/… partitions diff --git a/units/meson.build b/units/meson.build index e4ac6ced64..3785e15dec 100644 --- a/units/meson.build +++ b/units/meson.build @@ -97,6 +97,7 @@ units = [ 'sockets.target.wants/'], ['systemd-networkd.socket', 'ENABLE_NETWORKD', join_paths(pkgsysconfdir, 'system/sockets.target.wants/')], + ['systemd-reboot.service', ''], ['systemd-rfkill.socket', 'ENABLE_RFKILL'], ['systemd-tmpfiles-clean.timer', '', 'timers.target.wants/'], @@ -182,7 +183,6 @@ in_units = [ ['systemd-quotacheck.service', 'ENABLE_QUOTACHECK'], ['systemd-random-seed.service', 'ENABLE_RANDOMSEED', 'sysinit.target.wants/'], - ['systemd-reboot.service', ''], ['systemd-remount-fs.service', '', 'local-fs.target.wants/'], ['systemd-resolved.service', 'ENABLE_RESOLVE', diff --git a/units/systemd-reboot.service.in b/units/systemd-reboot.service similarity index 89% rename from units/systemd-reboot.service.in rename to units/systemd-reboot.service index 4763ccfdca..505f60aabf 100644 --- a/units/systemd-reboot.service.in +++ b/units/systemd-reboot.service @@ -13,7 +13,4 @@ Documentation=man:systemd-halt.service(8) DefaultDependencies=no Requires=shutdown.target umount.target final.target After=shutdown.target umount.target final.target - -[Service] -Type=oneshot -ExecStart=@SYSTEMCTL@ --force reboot +SuccessAction=reboot-force From afa6206583dfbc93e29981cb5d713841e4ca2865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 15:34:57 +0200 Subject: [PATCH 11/13] units: use SuccessAction=poweroff-force in systemd-poweroff.service Explicit systemctl calls remain in systemd-halt.service and the system systemd-exit.service. To convert systemd-halt, we'd need to add SuccessAction=halt-force. Halting doesn't make much sense, so let's just leave that is. systemd-exit.service will be converted in the next commit. --- units/meson.build | 2 +- ...{systemd-poweroff.service.in => systemd-poweroff.service} | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) rename units/{systemd-poweroff.service.in => systemd-poweroff.service} (89%) diff --git a/units/meson.build b/units/meson.build index 3785e15dec..9d372c78a8 100644 --- a/units/meson.build +++ b/units/meson.build @@ -97,6 +97,7 @@ units = [ 'sockets.target.wants/'], ['systemd-networkd.socket', 'ENABLE_NETWORKD', join_paths(pkgsysconfdir, 'system/sockets.target.wants/')], + ['systemd-poweroff.service', ''], ['systemd-reboot.service', ''], ['systemd-rfkill.socket', 'ENABLE_RFKILL'], ['systemd-tmpfiles-clean.timer', '', @@ -179,7 +180,6 @@ in_units = [ ['systemd-nspawn@.service', ''], ['systemd-portabled.service', 'ENABLE_PORTABLED', 'dbus-org.freedesktop.portable1.service'], - ['systemd-poweroff.service', ''], ['systemd-quotacheck.service', 'ENABLE_QUOTACHECK'], ['systemd-random-seed.service', 'ENABLE_RANDOMSEED', 'sysinit.target.wants/'], diff --git a/units/systemd-poweroff.service.in b/units/systemd-poweroff.service similarity index 89% rename from units/systemd-poweroff.service.in rename to units/systemd-poweroff.service index e9fd655508..8d1d54389b 100644 --- a/units/systemd-poweroff.service.in +++ b/units/systemd-poweroff.service @@ -13,7 +13,4 @@ Documentation=man:systemd-halt.service(8) DefaultDependencies=no Requires=shutdown.target umount.target final.target After=shutdown.target umount.target final.target - -[Service] -Type=oneshot -ExecStart=@SYSTEMCTL@ --force poweroff +SuccessAction=poweroff-force From a400bd8c2a6285576edf8e2147e1d17aab129501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Oct 2018 16:34:45 +0200 Subject: [PATCH 12/13] units: allow and use SuccessAction=exit-force in system systemd-exit.service C.f. 287419c119ef961db487a281162ab037eba70c61: 'systemctl exit 42' can be used to set an exit value and pulls in exit.target, which pulls in systemd-exit.service, which calls org.fdo.Manager.Exit, which calls method_exit(), which sets the objective to MANAGER_EXIT. Allow the same to happen through SuccessAction=exit. v2: update for 'exit' and 'exit-force' --- man/systemd.unit.xml | 7 +++-- src/core/emergency-action.c | 27 +++++++++++-------- src/test/test-emergency-action.c | 6 ++--- units/meson.build | 2 +- ...d-exit.service.in => systemd-exit.service} | 5 +--- 5 files changed, 24 insertions(+), 23 deletions(-) rename units/{systemd-exit.service.in => systemd-exit.service} (88%) diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 9f65394b06..467b905f14 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -872,9 +872,8 @@ Takes one of , , , , , , , , and . In system mode, - all options except and are allowed. In user mode, only - , , and are allowed. Both options default - to . + all options are allowed. In user mode, only , , and + are allowed. Both options default to . If is set, no action will be triggered. causes a reboot following the normal shutdown procedure (i.e. equivalent to systemctl reboot). @@ -884,7 +883,7 @@ reboot2 system call, which might result in data loss. Similarly, , , have the effect of powering down the system with similar - semantics. causes the user manager to exit following the normal shutdown procedure, and + semantics. causes the manager to exit following the normal shutdown procedure, and causes it terminate without shutting down services. diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c index 3f0c11a3f2..e12ff81601 100644 --- a/src/core/emergency-action.c +++ b/src/core/emergency-action.c @@ -10,6 +10,7 @@ #include "special.h" #include "string-table.h" #include "terminal-util.h" +#include "virt.h" static void log_and_status(Manager *m, const char *message, const char *reason) { log_warning("%s: %s", message, reason); @@ -71,12 +72,14 @@ int emergency_action( break; case EMERGENCY_ACTION_EXIT: - assert(MANAGER_IS_USER(m)); + if (MANAGER_IS_USER(m) || detect_container() > 0) { + log_and_status(m, "Exiting", reason); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); + break; + } - log_and_status(m, "Exiting", reason); - - (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); - break; + log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action."); + _fallthrough_; case EMERGENCY_ACTION_POWEROFF: log_and_status(m, "Powering off", reason); @@ -84,11 +87,14 @@ int emergency_action( break; case EMERGENCY_ACTION_EXIT_FORCE: - assert(MANAGER_IS_USER(m)); + if (MANAGER_IS_USER(m) || detect_container() > 0) { + log_and_status(m, "Exiting immediately", reason); + m->objective = MANAGER_EXIT; + break; + } - log_and_status(m, "Exiting immediately", reason); - m->objective = MANAGER_EXIT; - break; + log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action."); + _fallthrough_; case EMERGENCY_ACTION_POWEROFF_FORCE: log_and_status(m, "Forcibly powering off", reason); @@ -135,8 +141,7 @@ int parse_emergency_action( if (x < 0) return -EINVAL; - if ((system && x >= _EMERGENCY_ACTION_FIRST_USER_ACTION) || - (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)) + if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION) return -EOPNOTSUPP; *ret = x; diff --git a/src/test/test-emergency-action.c b/src/test/test-emergency-action.c index 493b23227e..8ce28ed9f5 100644 --- a/src/test/test-emergency-action.c +++ b/src/test/test-emergency-action.c @@ -36,10 +36,10 @@ static void test_parse_emergency_action(void) { assert_se(parse_emergency_action("poweroff-force", true, &x) == 0); assert_se(x == EMERGENCY_ACTION_POWEROFF_FORCE); assert_se(parse_emergency_action("poweroff-immediate", true, &x) == 0); - assert_se(parse_emergency_action("exit", true, &x) == -EOPNOTSUPP); - assert_se(parse_emergency_action("exit-force", true, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("exit", true, &x) == 0); + assert_se(parse_emergency_action("exit-force", true, &x) == 0); assert_se(parse_emergency_action("exit-forcee", true, &x) == -EINVAL); - assert_se(x == EMERGENCY_ACTION_POWEROFF_IMMEDIATE); + assert_se(x == EMERGENCY_ACTION_EXIT_FORCE); } int main(int argc, char **argv) { diff --git a/units/meson.build b/units/meson.build index 9d372c78a8..3cc86b3e92 100644 --- a/units/meson.build +++ b/units/meson.build @@ -85,6 +85,7 @@ units = [ 'multi-user.target.wants/'], ['systemd-coredump.socket', 'ENABLE_COREDUMP', 'sockets.target.wants/'], + ['systemd-exit.service', ''], ['systemd-initctl.socket', '', 'sockets.target.wants/'], ['systemd-journal-gatewayd.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'], @@ -135,7 +136,6 @@ in_units = [ ['systemd-binfmt.service', 'ENABLE_BINFMT', 'sysinit.target.wants/'], ['systemd-coredump@.service', 'ENABLE_COREDUMP'], - ['systemd-exit.service', ''], ['systemd-firstboot.service', 'ENABLE_FIRSTBOOT', 'sysinit.target.wants/'], ['systemd-fsck-root.service', ''], diff --git a/units/systemd-exit.service.in b/units/systemd-exit.service similarity index 88% rename from units/systemd-exit.service.in rename to units/systemd-exit.service index 2fb6ebd767..6029b13a05 100644 --- a/units/systemd-exit.service.in +++ b/units/systemd-exit.service @@ -13,7 +13,4 @@ Documentation=man:systemd.special(7) DefaultDependencies=no Requires=shutdown.target After=shutdown.target - -[Service] -Type=oneshot -ExecStart=@SYSTEMCTL@ --force exit +SuccessAction=exit From c7adcb1af9946d0672c16bb4bb7eedf39b3d1fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 17 Oct 2018 17:27:20 +0200 Subject: [PATCH 13/13] core: do not "warn" about mundane emergency actions For example in a container we'd log: Oct 17 17:01:10 rawhide systemd[1]: Started Power-Off. Oct 17 17:01:10 rawhide systemd[1]: Forcibly powering off: unit succeeded Oct 17 17:01:10 rawhide systemd[1]: Reached target Power-Off. Oct 17 17:01:10 rawhide systemd[1]: Shutting down. and on the console we'd write (in red) [ !! ] Forcibly powering off: unit succeeded This is not useful in any way, and the fact that we're calling an "emergency action" is an internal implementation detail. Let's log about c-a-d and the watchdog actions only. --- src/core/emergency-action.c | 29 ++++++++++++++++------------- src/core/emergency-action.h | 1 + src/core/job.c | 3 ++- src/core/manager.c | 2 +- src/core/unit.c | 3 ++- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c index e12ff81601..c91d2bf5ff 100644 --- a/src/core/emergency-action.c +++ b/src/core/emergency-action.c @@ -12,11 +12,12 @@ #include "terminal-util.h" #include "virt.h" -static void log_and_status(Manager *m, const char *message, const char *reason) { - log_warning("%s: %s", message, reason); - manager_status_printf(m, STATUS_TYPE_EMERGENCY, - ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, - "%s: %s", message, reason); +static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) { + log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason); + if (warn) + manager_status_printf(m, STATUS_TYPE_EMERGENCY, + ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, + "%s: %s", message, reason); } int emergency_action( @@ -38,10 +39,12 @@ int emergency_action( return -ECANCELED; } + bool warn = FLAGS_SET(options, EMERGENCY_ACTION_WARN); + switch (action) { case EMERGENCY_ACTION_REBOOT: - log_and_status(m, "Rebooting", reason); + log_and_status(m, warn, "Rebooting", reason); (void) update_reboot_parameter_and_warn(reboot_arg); (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); @@ -49,7 +52,7 @@ int emergency_action( break; case EMERGENCY_ACTION_REBOOT_FORCE: - log_and_status(m, "Forcibly rebooting", reason); + log_and_status(m, warn, "Forcibly rebooting", reason); (void) update_reboot_parameter_and_warn(reboot_arg); m->objective = MANAGER_REBOOT; @@ -57,7 +60,7 @@ int emergency_action( break; case EMERGENCY_ACTION_REBOOT_IMMEDIATE: - log_and_status(m, "Rebooting immediately", reason); + log_and_status(m, warn, "Rebooting immediately", reason); sync(); @@ -73,7 +76,7 @@ int emergency_action( case EMERGENCY_ACTION_EXIT: if (MANAGER_IS_USER(m) || detect_container() > 0) { - log_and_status(m, "Exiting", reason); + log_and_status(m, warn, "Exiting", reason); (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); break; } @@ -82,13 +85,13 @@ int emergency_action( _fallthrough_; case EMERGENCY_ACTION_POWEROFF: - log_and_status(m, "Powering off", reason); + log_and_status(m, warn, "Powering off", reason); (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); break; case EMERGENCY_ACTION_EXIT_FORCE: if (MANAGER_IS_USER(m) || detect_container() > 0) { - log_and_status(m, "Exiting immediately", reason); + log_and_status(m, warn, "Exiting immediately", reason); m->objective = MANAGER_EXIT; break; } @@ -97,12 +100,12 @@ int emergency_action( _fallthrough_; case EMERGENCY_ACTION_POWEROFF_FORCE: - log_and_status(m, "Forcibly powering off", reason); + log_and_status(m, warn, "Forcibly powering off", reason); m->objective = MANAGER_POWEROFF; break; case EMERGENCY_ACTION_POWEROFF_IMMEDIATE: - log_and_status(m, "Powering off immediately", reason); + log_and_status(m, warn, "Powering off immediately", reason); sync(); diff --git a/src/core/emergency-action.h b/src/core/emergency-action.h index 453de0dbd2..1fc4a11e30 100644 --- a/src/core/emergency-action.h +++ b/src/core/emergency-action.h @@ -18,6 +18,7 @@ typedef enum EmergencyAction { typedef enum EmergencyActionFlags { EMERGENCY_ACTION_IS_WATCHDOG = 1 << 0, + EMERGENCY_ACTION_WARN = 1 << 1, } EmergencyActionFlags; #include "macro.h" diff --git a/src/core/job.c b/src/core/job.c index 23717d5e47..5a88f52f48 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -973,7 +973,8 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user u = j->unit; job_finish_and_invalidate(j, JOB_TIMEOUT, true, false); - emergency_action(u->manager, u->job_timeout_action, EMERGENCY_ACTION_IS_WATCHDOG, + emergency_action(u->manager, u->job_timeout_action, + EMERGENCY_ACTION_IS_WATCHDOG|EMERGENCY_ACTION_WARN, u->job_timeout_reboot_arg, "job timed out"); return 0; diff --git a/src/core/manager.c b/src/core/manager.c index 0c3109b34b..94e38be1ea 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2538,7 +2538,7 @@ static void manager_handle_ctrl_alt_del(Manager *m) { if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE) manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); else - emergency_action(m, m->cad_burst_action, 0, NULL, + emergency_action(m, m->cad_burst_action, EMERGENCY_ACTION_WARN, NULL, "Ctrl-Alt-Del was pressed more than 7 times within 2s"); } diff --git a/src/core/unit.c b/src/core/unit.c index 0806a50cce..0ce9318556 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1724,7 +1724,8 @@ int unit_start_limit_test(Unit *u) { log_unit_warning(u, "Start request repeated too quickly."); u->start_limit_hit = true; - return emergency_action(u->manager, u->start_limit_action, EMERGENCY_ACTION_IS_WATCHDOG, + return emergency_action(u->manager, u->start_limit_action, + EMERGENCY_ACTION_IS_WATCHDOG|EMERGENCY_ACTION_WARN, u->reboot_arg, "unit failed"); }