be0c12
From c0aa64901aa4d5d7c917fccf0993819fb1a1262f Mon Sep 17 00:00:00 2001
be0c12
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
be0c12
Date: Tue, 16 Oct 2018 16:34:45 +0200
be0c12
Subject: [PATCH] units: allow and use SuccessAction=exit-force in system
be0c12
 systemd-exit.service
be0c12
be0c12
C.f. 287419c119ef961db487a281162ab037eba70c61: 'systemctl exit 42' can be
be0c12
used to set an exit value and pulls in exit.target, which pulls in systemd-exit.service,
be0c12
which calls org.fdo.Manager.Exit, which calls method_exit(), which sets the objective
be0c12
to MANAGER_EXIT. Allow the same to happen through SuccessAction=exit.
be0c12
be0c12
v2: update for 'exit' and 'exit-force'
be0c12
(cherry picked from commit a400bd8c2a6285576edf8e2147e1d17aab129501)
be0c12
be0c12
Related: #1860899
be0c12
---
be0c12
 man/systemd.unit.xml                          |  7 +++--
be0c12
 src/core/emergency-action.c                   | 27 +++++++++++--------
be0c12
 src/test/test-emergency-action.c              |  6 ++---
be0c12
 units/meson.build                             |  2 +-
be0c12
 ...d-exit.service.in => systemd-exit.service} |  5 +---
be0c12
 5 files changed, 24 insertions(+), 23 deletions(-)
be0c12
 rename units/{systemd-exit.service.in => systemd-exit.service} (88%)
be0c12
be0c12
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
be0c12
index 5772a6684e..e80c760dd6 100644
be0c12
--- a/man/systemd.unit.xml
be0c12
+++ b/man/systemd.unit.xml
be0c12
@@ -881,9 +881,8 @@
be0c12
         Takes one of <option>none</option>, <option>reboot</option>, <option>reboot-force</option>,
be0c12
         <option>reboot-immediate</option>, <option>poweroff</option>, <option>poweroff-force</option>,
be0c12
         <option>poweroff-immediate</option>, <option>exit</option>, and <option>exit-force</option>. In system mode,
be0c12
-        all options except <option>exit</option> and <option>exit-force</option> are allowed. In user mode, only
be0c12
-        <option>none</option>, <option>exit</option>, and <option>exit-force</option> are allowed. Both options default
be0c12
-        to <option>none</option>.</para>
be0c12
+        all options are allowed. In user mode, only <option>none</option>, <option>exit</option>, and
be0c12
+        <option>exit-force</option> are allowed. Both options default to <option>none</option>.</para>
be0c12
 
be0c12
         <para>If <option>none</option> is set, no action will be triggered. <option>reboot</option> causes a reboot
be0c12
         following the normal shutdown procedure (i.e. equivalent to <command>systemctl reboot</command>).
be0c12
@@ -893,7 +892,7 @@
be0c12
         <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call, which
be0c12
         might result in data loss. Similarly, <option>poweroff</option>, <option>poweroff-force</option>,
be0c12
         <option>poweroff-immediate</option> have the effect of powering down the system with similar
be0c12
-        semantics. <option>exit</option> causes the user manager to exit following the normal shutdown procedure, and
be0c12
+        semantics. <option>exit</option> causes the manager to exit following the normal shutdown procedure, and
be0c12
         <option>exit-force</option> causes it terminate without shutting down services.</para></listitem>
be0c12
       </varlistentry>
be0c12
 
be0c12
diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c
be0c12
index e9e757dfa3..44b92ae6f8 100644
be0c12
--- a/src/core/emergency-action.c
be0c12
+++ b/src/core/emergency-action.c
be0c12
@@ -13,6 +13,7 @@
be0c12
 #include "special.h"
be0c12
 #include "string-table.h"
be0c12
 #include "terminal-util.h"
be0c12
+#include "virt.h"
be0c12
 
be0c12
 static void log_and_status(Manager *m, const char *message, const char *reason) {
be0c12
         log_warning("%s: %s", message, reason);
be0c12
@@ -73,12 +74,14 @@ int emergency_action(
be0c12
                 break;
be0c12
 
be0c12
         case EMERGENCY_ACTION_EXIT:
be0c12
-                assert(MANAGER_IS_USER(m));
be0c12
-
be0c12
-                log_and_status(m, "Exiting", reason);
be0c12
+                if (MANAGER_IS_USER(m) || detect_container() > 0) {
be0c12
+                        log_and_status(m, "Exiting", reason);
be0c12
+                        (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
be0c12
+                        break;
be0c12
+                }
be0c12
 
be0c12
-                (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
be0c12
-                break;
be0c12
+                log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action.");
be0c12
+                _fallthrough_;
be0c12
 
be0c12
         case EMERGENCY_ACTION_POWEROFF:
be0c12
                 log_and_status(m, "Powering off", reason);
be0c12
@@ -86,11 +89,14 @@ int emergency_action(
be0c12
                 break;
be0c12
 
be0c12
         case EMERGENCY_ACTION_EXIT_FORCE:
be0c12
-                assert(MANAGER_IS_USER(m));
be0c12
+                if (MANAGER_IS_USER(m) || detect_container() > 0) {
be0c12
+                        log_and_status(m, "Exiting immediately", reason);
be0c12
+                        m->exit_code = MANAGER_EXIT;
be0c12
+                        break;
be0c12
+                }
be0c12
 
be0c12
-                log_and_status(m, "Exiting immediately", reason);
be0c12
-                m->exit_code = MANAGER_EXIT;
be0c12
-                break;
be0c12
+                log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action.");
be0c12
+                _fallthrough_;
be0c12
 
be0c12
         case EMERGENCY_ACTION_POWEROFF_FORCE:
be0c12
                 log_and_status(m, "Forcibly powering off", reason);
be0c12
@@ -137,8 +143,7 @@ int parse_emergency_action(
be0c12
         if (x < 0)
be0c12
                 return -EINVAL;
be0c12
 
be0c12
-        if ((system && x >= _EMERGENCY_ACTION_FIRST_USER_ACTION) ||
be0c12
-            (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION))
be0c12
+        if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)
be0c12
                 return -EOPNOTSUPP;
be0c12
 
be0c12
         *ret = x;
be0c12
diff --git a/src/test/test-emergency-action.c b/src/test/test-emergency-action.c
be0c12
index 493b23227e..8ce28ed9f5 100644
be0c12
--- a/src/test/test-emergency-action.c
be0c12
+++ b/src/test/test-emergency-action.c
be0c12
@@ -36,10 +36,10 @@ static void test_parse_emergency_action(void) {
be0c12
         assert_se(parse_emergency_action("poweroff-force", true, &x) == 0);
be0c12
         assert_se(x == EMERGENCY_ACTION_POWEROFF_FORCE);
be0c12
         assert_se(parse_emergency_action("poweroff-immediate", true, &x) == 0);
be0c12
-        assert_se(parse_emergency_action("exit", true, &x) == -EOPNOTSUPP);
be0c12
-        assert_se(parse_emergency_action("exit-force", true, &x) == -EOPNOTSUPP);
be0c12
+        assert_se(parse_emergency_action("exit", true, &x) == 0);
be0c12
+        assert_se(parse_emergency_action("exit-force", true, &x) == 0);
be0c12
         assert_se(parse_emergency_action("exit-forcee", true, &x) == -EINVAL);
be0c12
-        assert_se(x == EMERGENCY_ACTION_POWEROFF_IMMEDIATE);
be0c12
+        assert_se(x == EMERGENCY_ACTION_EXIT_FORCE);
be0c12
 }
be0c12
 
be0c12
 int main(int argc, char **argv) {
be0c12
diff --git a/units/meson.build b/units/meson.build
be0c12
index 6fa804148b..a74fa95195 100644
be0c12
--- a/units/meson.build
be0c12
+++ b/units/meson.build
be0c12
@@ -86,6 +86,7 @@ units = [
be0c12
          'multi-user.target.wants/'],
be0c12
         ['systemd-coredump.socket',             'ENABLE_COREDUMP',
be0c12
          'sockets.target.wants/'],
be0c12
+        ['systemd-exit.service',                 ''],
be0c12
         ['systemd-initctl.socket',              '',
be0c12
          'sockets.target.wants/'],
be0c12
         ['systemd-journal-gatewayd.socket',     'ENABLE_REMOTE HAVE_MICROHTTPD'],
be0c12
@@ -135,7 +136,6 @@ in_units = [
be0c12
         ['systemd-binfmt.service',               'ENABLE_BINFMT',
be0c12
          'sysinit.target.wants/'],
be0c12
         ['systemd-coredump@.service',            'ENABLE_COREDUMP'],
be0c12
-        ['systemd-exit.service',                 ''],
be0c12
         ['systemd-firstboot.service',            'ENABLE_FIRSTBOOT',
be0c12
          'sysinit.target.wants/'],
be0c12
         ['systemd-fsck-root.service',            ''],
be0c12
diff --git a/units/systemd-exit.service.in b/units/systemd-exit.service
be0c12
similarity index 88%
be0c12
rename from units/systemd-exit.service.in
be0c12
rename to units/systemd-exit.service
be0c12
index 2fb6ebd767..6029b13a05 100644
be0c12
--- a/units/systemd-exit.service.in
be0c12
+++ b/units/systemd-exit.service
be0c12
@@ -13,7 +13,4 @@ Documentation=man:systemd.special(7)
be0c12
 DefaultDependencies=no
be0c12
 Requires=shutdown.target
be0c12
 After=shutdown.target
be0c12
-
be0c12
-[Service]
be0c12
-Type=oneshot
be0c12
-ExecStart=@SYSTEMCTL@ --force exit
be0c12
+SuccessAction=exit