Blob Blame History Raw
From f07756bfe25c64119704c93a634162d6c88b5c89 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 22 Aug 2014 16:59:46 +0200
Subject: [PATCH] core: introduce "poweroff" as new failure action types

Also, change the default action on a system start-up timeout to powering off.
---
 man/systemd-system.conf.xml |  2 +-
 man/systemd.service.xml     | 31 +++++++++++++++++++-----------
 src/core/failure-action.c   | 46 +++++++++++++++++++++++++++++++++++++++++----
 src/core/failure-action.h   |  3 +++
 src/core/main.c             |  2 +-
 src/core/manager.c          |  2 +-
 src/core/shutdown.c         |  3 +--
 src/core/system.conf        |  2 +-
 8 files changed, 70 insertions(+), 21 deletions(-)

diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index 48690024f4..1fad1dba80 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -298,7 +298,7 @@
                                 setting, see
                                 <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
                                 for details. Defaults to
-                                <option>reboot-force</option>. <varname>StartTimeoutRebootArgument=</varname>
+                                <option>poweroff-force</option>. <varname>StartTimeoutRebootArgument=</varname>
                                 configures an optional reboot string
                                 to pass to the
                                 <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 20d2a0d755..8b17f857ce 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -1131,26 +1131,35 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
                                 hit. Takes one of
                                 <option>none</option>,
                                 <option>reboot</option>,
-                                <option>reboot-force</option>, or
-                                <option>reboot-immediate</option>. If
-                                <option>none</option> is set,
-                                hitting the rate limit will trigger no
-                                action besides that the start will not
-                                be permitted. <option>reboot</option>
+                                <option>reboot-force</option>,
+                                <option>reboot-immediate</option>,
+                                <option>poweroff</option>,
+                                <option>poweroff-force</option> or
+                                <option>poweroff-immediate</option>. If
+                                <option>none</option> is set, hitting
+                                the rate limit will trigger no action
+                                besides that the start will not be
+                                permitted. <option>reboot</option>
                                 causes a reboot following the normal
                                 shutdown procedure (i.e. equivalent to
                                 <command>systemctl reboot</command>).
-                                <option>reboot-force</option> causes
-                                a forced reboot which will terminate
-                                all processes forcibly but should
-                                cause no dirty file systems on reboot
+                                <option>reboot-force</option> causes a
+                                forced reboot which will terminate all
+                                processes forcibly but should cause no
+                                dirty file systems on reboot
                                 (i.e. equivalent to <command>systemctl
                                 reboot -f</command>) and
                                 <option>reboot-immediate</option>
                                 causes immediate execution of the
                                 <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
                                 system call, which might result in
-                                data loss. Defaults to
+                                data loss. Similar,
+                                <option>poweroff</option>,
+                                <option>poweroff-force</option>,
+                                <option>poweroff-immediate</option>
+                                have the effect of powering down the
+                                system with similar
+                                semantics. Defaults to
                                 <option>none</option>.</para></listitem>
                         </varlistentry>
 
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
index ca807b68da..941747429f 100644
--- a/src/core/failure-action.c
+++ b/src/core/failure-action.c
@@ -40,10 +40,19 @@ int failure_action(
         assert(action >= 0);
         assert(action < _FAILURE_ACTION_MAX);
 
-        switch (action) {
+        if (action == FAILURE_ACTION_NONE)
+                return -ECANCELED;
 
-        case FAILURE_ACTION_NONE:
-                break;
+        if (m->running_as == SYSTEMD_USER) {
+                /* Downgrade all options to simply exiting if we run
+                 * in user mode */
+
+                log_warning("Exiting as result of failure.");
+                m->exit_code = MANAGER_EXIT;
+                return -ECANCELED;
+        }
+
+        switch (action) {
 
         case FAILURE_ACTION_REBOOT: {
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -78,6 +87,32 @@ int failure_action(
                 reboot(RB_AUTOBOOT);
                 break;
 
+        case FAILURE_ACTION_POWEROFF: {
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+
+                log_warning("Powering off as result of failure.");
+
+                r = manager_add_job_by_name(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE, true, &error, NULL);
+                if (r < 0)
+                        log_error("Failed to poweroff: %s.", bus_error_message(&error, r));
+
+                break;
+        }
+
+        case FAILURE_ACTION_POWEROFF_FORCE:
+                log_warning("Forcibly powering off as result of failure.");
+                m->exit_code = MANAGER_POWEROFF;
+                break;
+
+        case FAILURE_ACTION_POWEROFF_IMMEDIATE:
+                log_warning("Powering off immediately as result of failure.");
+
+                sync();
+
+                log_info("Powering off.");
+                reboot(RB_POWER_OFF);
+                break;
+
         default:
                 assert_not_reached("Unknown failure action");
         }
@@ -89,6 +124,9 @@ static const char* const failure_action_table[_FAILURE_ACTION_MAX] = {
         [FAILURE_ACTION_NONE] = "none",
         [FAILURE_ACTION_REBOOT] = "reboot",
         [FAILURE_ACTION_REBOOT_FORCE] = "reboot-force",
-        [FAILURE_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate"
+        [FAILURE_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
+        [FAILURE_ACTION_POWEROFF] = "poweroff",
+        [FAILURE_ACTION_POWEROFF_FORCE] = "poweroff-force",
+        [FAILURE_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate"
 };
 DEFINE_STRING_TABLE_LOOKUP(failure_action, FailureAction);
diff --git a/src/core/failure-action.h b/src/core/failure-action.h
index 5353192f31..1af4dd987b 100644
--- a/src/core/failure-action.h
+++ b/src/core/failure-action.h
@@ -27,6 +27,9 @@ typedef enum FailureAction {
         FAILURE_ACTION_REBOOT,
         FAILURE_ACTION_REBOOT_FORCE,
         FAILURE_ACTION_REBOOT_IMMEDIATE,
+        FAILURE_ACTION_POWEROFF,
+        FAILURE_ACTION_POWEROFF_FORCE,
+        FAILURE_ACTION_POWEROFF_IMMEDIATE,
         _FAILURE_ACTION_MAX,
         _FAILURE_ACTION_INVALID = -1
 } FailureAction;
diff --git a/src/core/main.c b/src/core/main.c
index ed690162bf..bd148b1b33 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -117,7 +117,7 @@ static bool arg_default_cpu_accounting = false;
 static bool arg_default_blockio_accounting = false;
 static bool arg_default_memory_accounting = false;
 static usec_t arg_start_timeout_usec = DEFAULT_MANAGER_START_TIMEOUT_USEC;
-static FailureAction arg_start_timeout_action = FAILURE_ACTION_REBOOT_FORCE;
+static FailureAction arg_start_timeout_action = FAILURE_ACTION_POWEROFF_FORCE;
 static char *arg_start_timeout_reboot_arg = NULL;
 
 static void nop_handler(int sig) {}
diff --git a/src/core/manager.c b/src/core/manager.c
index 7508fefaef..7639aeef19 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -436,7 +436,7 @@ int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
         m->default_timer_accuracy_usec = USEC_PER_MINUTE;
         m->start_timeout_usec = DEFAULT_MANAGER_START_TIMEOUT_USEC;
-        m->start_timeout_action = FAILURE_ACTION_REBOOT_FORCE;
+        m->start_timeout_action = FAILURE_ACTION_POWEROFF_FORCE;
 
         m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 1abc140e7d..0e2ea5754f 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -435,8 +435,7 @@ int main(int argc, char *argv[]) {
 
                         if (read_one_line_file(REBOOT_PARAM_FILE, &param) >= 0) {
                                 log_info("Rebooting with argument '%s'.", param);
-                                syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
-                                        LINUX_REBOOT_CMD_RESTART2, param);
+                                syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
                         }
                 }
 
diff --git a/src/core/system.conf b/src/core/system.conf
index 45448de328..5a723bb20e 100644
--- a/src/core/system.conf
+++ b/src/core/system.conf
@@ -24,7 +24,7 @@
 #SystemCallArchitectures=
 #TimerSlackNSec=
 #StartTimeoutSec=15min
-#StartTimeoutAction=reboot-force
+#StartTimeoutAction=poweroff-force
 #StartTimeoutRebootArgument=
 #DefaultTimerAccuracySec=1min
 #DefaultStandardOutput=journal