From f48077762390d0d189985fe710e2af140dc05964 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Tue, 1 Aug 2017 11:40:51 +0100 Subject: [PATCH 1/4] =?UTF-8?q?units:=20do=20not=20install=20rescue.target?= =?UTF-8?q?=20for=20alt-=E2=86=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rescue.target does not work well for this. It is not meant to be started, only isolated. Fixes #6493 --- units/rescue.target | 3 --- 1 file changed, 3 deletions(-) diff --git a/units/rescue.target b/units/rescue.target index 3f59b14339..bd92ed2df3 100644 --- a/units/rescue.target +++ b/units/rescue.target @@ -11,6 +11,3 @@ Documentation=man:systemd.special(7) Requires=sysinit.target rescue.service After=sysinit.target rescue.service AllowIsolate=yes - -[Install] -Alias=kbrequest.target From dcb1468861deddc0b76ee2e05a3ad9e52f2faacc Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Mon, 31 Jul 2017 17:50:38 +0100 Subject: [PATCH 2/4] man: dbus method Manager.Exit() does not start exit.target It's like Manager.PowerOff(), which does not start poweroff.target. Instead, the dbus methods are used for `systemctl --force exit` or `systemctl --force poweroff`. They shut down the system without processing individual unit's ExecStop or TimeoutStopSec. --- man/systemd.special.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/man/systemd.special.xml b/man/systemd.special.xml index b4ed3eb8f2..9c916bee6f 100644 --- a/man/systemd.special.xml +++ b/man/systemd.special.xml @@ -238,8 +238,7 @@ poweroff.target on non-container systems, and also works in containers. - systemd will start this unit when it receives a - request to shut down over D-Bus or a + systemd will start this unit when it receives the SIGTERM or SIGINT signal when running as user service daemon. From c75fbadac6bbbf8aa2b7c87be09dbea1f7715188 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 2 Aug 2017 16:19:22 +0100 Subject: [PATCH 3/4] manager: remove fallback for user/exit.target The comment here was misleading: the job can fail to enqueue for reasons other than the target not existing. The fallback caused an error to be logged, and dates back to when the "user" directory was named "session". units/session/exit.target was added later the same year. This is consistent with the documentation (man systemd), and the handling of similar signals. It's also consistent with `systemctl exit`, which is what most people would expect. --- src/core/manager.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 4d215d5692..1387341367 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2012,7 +2012,7 @@ static int manager_dispatch_sigchld(Manager *m) { return 0; } -static int manager_start_target(Manager *m, const char *name, JobMode mode) { +static void manager_start_target(Manager *m, const char *name, JobMode mode) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; @@ -2021,8 +2021,6 @@ static int manager_start_target(Manager *m, const char *name, JobMode mode) { r = manager_add_job_by_name(m, JOB_START, name, mode, &error, NULL); if (r < 0) log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r)); - - return r; } static void manager_handle_ctrl_alt_del(Manager *m) { @@ -2092,17 +2090,10 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t /* Fall through */ case SIGINT: - if (MANAGER_IS_SYSTEM(m)) { + if (MANAGER_IS_SYSTEM(m)) manager_handle_ctrl_alt_del(m); - break; - } - - /* Run the exit target if there is one, if not, just exit. */ - if (manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE) < 0) { - m->exit_code = MANAGER_EXIT; - return 0; - } - + else + manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE); break; case SIGWINCH: From d60cb656fc63c24b430421764b7d0322857d34fd Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Mon, 31 Jul 2017 17:36:58 +0100 Subject: [PATCH 4/4] manager: fix job mode when signalled to shutdown etc The irreversible job mode is required to ensure that shutdown is not interrupted by the activation of a unit with a conflict. We already used the correct job mode for `ctrl-alt-del.target`. But not for `exit.target` (SIGINT of user manager). The SIGRT shutdown signals also needed fixing. Also change SIGRTMIN+0 to isolate default.target, instead of starting it. The previous behaviour was documented. However there was no reason given for it, nor can we provide one. The problem that isolate is too aggressive anywhere outside of emergency.target (#2607) is orthogonal. This feature is "accessible by different means and only really a safety net"; it is confusing for it to differ from `systemctl default` without explanation. `AllowIsolate=yes` is retained on poweroff.target etc. for backwards compatibility. `sigpwr.target` is also an obvious candidate for linking to a shutdown target. Unforunately it is also a possible hook for implementing some logic like system V init did, reading `/etc/powerstatus`. If we switched to starting `sigpwr.target` with REPLACE_IRREVERSIBLY, attempts to run `systemctl shutdown` from it would fail, if they had not thought to set `DefaultDependencies=no`. We had provided no examples for `sigpwr`, and the whole idea is cruft to keep legacy people happy. For the moment, I leave `sigpwr` alone, with no risk of disrupting anyone's previously-working, half-working, or untested setup. Fixes #6484. See also #6471 --- man/systemctl.xml | 3 ++- man/systemd.xml | 39 ++++++++++++++++++++++----------------- src/core/manager.c | 26 +++++++++++++++----------- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 83cc4eb560..0778c38ca4 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -295,7 +295,8 @@ transactions from replacing these jobs (or even being enqueued while the irreversible jobs are still pending). Irreversible jobs can still be cancelled using the cancel - command. + command. This job mode should be used on any transaction which + pulls in shutdown.target. isolate is only valid for start operations and causes all other units to be stopped when the diff --git a/man/systemd.xml b/man/systemd.xml index e8178ca4bb..b455b605cb 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -561,7 +561,8 @@ systemd user managers will start the exit.target unit when this signal is received. This is mostly equivalent to systemctl - --user start exit.target. + --user start exit.target + --job-mode=replace-irreversible. @@ -570,13 +571,13 @@ Upon receiving this signal the systemd system manager will start the ctrl-alt-del.target unit. This is mostly - equivalent to systemctl start - ctl-alt-del.target. If this signal is received more - than 7 times per 2s, an immediate reboot is triggered. - Note that pressing Ctrl-Alt-Del on the console will trigger - this signal. Hence, if a reboot is hanging, pressing - Ctrl-Alt-Del more than 7 times in 2s is a relatively safe way - to trigger an immediate reboot. + equivalent to systemctl start ctl-alt-del.target + --job-mode=replace-irreversible. If this signal is + received more than 7 times per 2s, an immediate reboot is + triggered. Note that pressing Ctrl-Alt-Del on the console + will trigger this signal. Hence, if a reboot is hanging, + pressing Ctrl-Alt-Del more than 7 times in 2s is a relatively + safe way to trigger an immediate reboot. systemd user managers treat this signal the same way as SIGTERM. @@ -634,7 +635,7 @@ Enters default mode, starts the default.target unit. This is mostly - equivalent to systemctl start + equivalent to systemctl isolate default.target. @@ -661,8 +662,9 @@ Halts the machine, starts the halt.target unit. This is mostly - equivalent to systemctl start - halt.target. + equivalent to systemctl start halt.target + --job-mode=replace-irreversible. + @@ -670,8 +672,9 @@ Powers off the machine, starts the poweroff.target unit. This is mostly - equivalent to systemctl start - poweroff.target. + equivalent to systemctl start poweroff.target + --job-mode=replace-irreversible. + @@ -679,8 +682,9 @@ Reboots the machine, starts the reboot.target unit. This is mostly - equivalent to systemctl start - reboot.target. + equivalent to systemctl start reboot.target + --job-mode=replace-irreversible. + @@ -688,8 +692,9 @@ Reboots the machine via kexec, starts the kexec.target unit. This is mostly - equivalent to systemctl start - kexec.target. + equivalent to systemctl start kexec.target + --job-mode=replace-irreversible. + diff --git a/src/core/manager.c b/src/core/manager.c index 1387341367..939d117ad1 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2093,7 +2093,8 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t if (MANAGER_IS_SYSTEM(m)) manager_handle_ctrl_alt_del(m); else - manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE); + manager_start_target(m, SPECIAL_EXIT_TARGET, + JOB_REPLACE_IRREVERSIBLY); break; case SIGWINCH: @@ -2161,14 +2162,17 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t default: { /* Starting SIGRTMIN+0 */ - static const char * const target_table[] = { - [0] = SPECIAL_DEFAULT_TARGET, - [1] = SPECIAL_RESCUE_TARGET, - [2] = SPECIAL_EMERGENCY_TARGET, - [3] = SPECIAL_HALT_TARGET, - [4] = SPECIAL_POWEROFF_TARGET, - [5] = SPECIAL_REBOOT_TARGET, - [6] = SPECIAL_KEXEC_TARGET + static const struct { + const char *target; + JobMode mode; + } target_table[] = { + [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE }, + [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE }, + [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE }, + [3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY }, + [4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY }, + [5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY }, + [6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY } }; /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */ @@ -2182,8 +2186,8 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t if ((int) sfsi.ssi_signo >= SIGRTMIN+0 && (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) { int idx = (int) sfsi.ssi_signo - SIGRTMIN; - manager_start_target(m, target_table[idx], - (idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE); + manager_start_target(m, target_table[idx].target, + target_table[idx].mode); break; }