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
This commit is contained in:
Alan Jenkins 2017-07-31 17:36:58 +01:00
parent c75fbadac6
commit d60cb656fc
3 changed files with 39 additions and 29 deletions

View File

@ -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 <command>cancel</command>
command.</para>
command. This job mode should be used on any transaction which
pulls in <filename>shutdown.target</filename>.</para>
<para><literal>isolate</literal> is only valid for start
operations and causes all other units to be stopped when the

View File

@ -561,7 +561,8 @@
<para>systemd user managers will start the
<filename>exit.target</filename> unit when this signal is
received. This is mostly equivalent to <command>systemctl
--user start exit.target</command>.</para></listitem>
--user start exit.target
--job-mode=replace-irreversible</command>.</para></listitem>
</varlistentry>
<varlistentry>
@ -570,13 +571,13 @@
<listitem><para>Upon receiving this signal the systemd system
manager will start the
<filename>ctrl-alt-del.target</filename> unit. This is mostly
equivalent to <command>systemctl start
ctl-alt-del.target</command>. 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.</para>
equivalent to <command>systemctl start ctl-alt-del.target
--job-mode=replace-irreversible</command>. 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.</para>
<para>systemd user managers treat this signal the same way as
<constant>SIGTERM</constant>.</para></listitem>
@ -634,7 +635,7 @@
<listitem><para>Enters default mode, starts the
<filename>default.target</filename> unit. This is mostly
equivalent to <command>systemctl start
equivalent to <command>systemctl isolate
default.target</command>.</para></listitem>
</varlistentry>
@ -661,8 +662,9 @@
<listitem><para>Halts the machine, starts the
<filename>halt.target</filename> unit. This is mostly
equivalent to <command>systemctl start
halt.target</command>.</para></listitem>
equivalent to <command>systemctl start halt.target
--job-mode=replace-irreversible</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -670,8 +672,9 @@
<listitem><para>Powers off the machine, starts the
<filename>poweroff.target</filename> unit. This is mostly
equivalent to <command>systemctl start
poweroff.target</command>.</para></listitem>
equivalent to <command>systemctl start poweroff.target
--job-mode=replace-irreversible</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -679,8 +682,9 @@
<listitem><para>Reboots the machine, starts the
<filename>reboot.target</filename> unit. This is mostly
equivalent to <command>systemctl start
reboot.target</command>.</para></listitem>
equivalent to <command>systemctl start reboot.target
--job-mode=replace-irreversible</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -688,8 +692,9 @@
<listitem><para>Reboots the machine via kexec, starts the
<filename>kexec.target</filename> unit. This is mostly
equivalent to <command>systemctl start
kexec.target</command>.</para></listitem>
equivalent to <command>systemctl start kexec.target
--job-mode=replace-irreversible</command>.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -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;
}