Zbigniew Jędrzejewski-Szmek 62fe94
From 2928b0a863091f8f291fddb168988711afd389ef Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 62fe94
From: Lennart Poettering <lennart@poettering.net>
Zbigniew Jędrzejewski-Szmek 62fe94
Date: Fri, 22 Aug 2014 16:36:38 +0200
Zbigniew Jędrzejewski-Szmek 62fe94
Subject: [PATCH] core: add support for a configurable system-wide start-up
Zbigniew Jędrzejewski-Szmek 62fe94
 timeout
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
When this system-wide start-up timeout is hit we execute one of the
Zbigniew Jędrzejewski-Szmek 62fe94
failure actions already implemented for services that fail.
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
This should not only be useful on embedded devices, but also on laptops
Zbigniew Jędrzejewski-Szmek 62fe94
which have the power-button reachable when the lid is closed. This
Zbigniew Jędrzejewski-Szmek 62fe94
devices, when in a backpack might get powered on by accident due to the
Zbigniew Jędrzejewski-Szmek 62fe94
easily reachable power button. We want to make sure that the system
Zbigniew Jędrzejewski-Szmek 62fe94
turns itself off if it starts up due this after a while.
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
When the system manages to fully start-up logind will suspend the
Zbigniew Jędrzejewski-Szmek 62fe94
machine by default if the lid is closed. However, in some cases we don't
Zbigniew Jędrzejewski-Szmek 62fe94
even get as far as logind, and the boot hangs much earlier, for example
Zbigniew Jędrzejewski-Szmek 62fe94
because we ask for a LUKS password that nobody ever enters.
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
Yeah, this is a real-life problem on my Yoga 13, which has one of those
Zbigniew Jędrzejewski-Szmek 62fe94
easily accessible power buttons, even if the device is closed.
Zbigniew Jędrzejewski-Szmek 62fe94
---
Zbigniew Jędrzejewski-Szmek 62fe94
 Makefile.am                 |  4 +-
Zbigniew Jędrzejewski-Szmek 62fe94
 man/systemd-system.conf.xml | 27 ++++++++++++-
Zbigniew Jędrzejewski-Szmek 62fe94
 man/systemd.service.xml     | 23 +++++------
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/failure-action.c   | 94 +++++++++++++++++++++++++++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/failure-action.h   | 40 +++++++++++++++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/main.c             | 13 +++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/manager.c          | 43 +++++++++++++++++++--
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/manager.h          | 10 +++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/service.c          | 77 ++++---------------------------------
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/service.h          | 16 +-------
Zbigniew Jędrzejewski-Szmek 62fe94
 src/core/system.conf        |  3 ++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/shared/util.c           | 21 ++++++++++
Zbigniew Jędrzejewski-Szmek 62fe94
 src/shared/util.h           |  2 +
Zbigniew Jędrzejewski-Szmek 62fe94
 src/test/test-tables.c      |  2 +-
Zbigniew Jędrzejewski-Szmek 62fe94
 14 files changed, 273 insertions(+), 102 deletions(-)
Zbigniew Jędrzejewski-Szmek 62fe94
 create mode 100644 src/core/failure-action.c
Zbigniew Jędrzejewski-Szmek 62fe94
 create mode 100644 src/core/failure-action.h
Zbigniew Jędrzejewski-Szmek 62fe94
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/Makefile.am b/Makefile.am
Zbigniew Jędrzejewski-Szmek 62fe94
index 4028112a62..cbf98bdac3 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/Makefile.am
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/Makefile.am
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1112,7 +1112,9 @@ libsystemd_core_la_SOURCES = \
Zbigniew Jędrzejewski-Szmek 62fe94
 	src/core/audit-fd.c \
Zbigniew Jędrzejewski-Szmek 62fe94
 	src/core/audit-fd.h \
Zbigniew Jędrzejewski-Szmek 62fe94
 	src/core/show-status.c \
Zbigniew Jędrzejewski-Szmek 62fe94
-	src/core/show-status.h
Zbigniew Jędrzejewski-Szmek 62fe94
+	src/core/show-status.h \
Zbigniew Jędrzejewski-Szmek 62fe94
+	src/core/failure-action.c \
Zbigniew Jędrzejewski-Szmek 62fe94
+	src/core/failure-action.h
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 if HAVE_KMOD
Zbigniew Jędrzejewski-Szmek 62fe94
 libsystemd_core_la_SOURCES += \
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
Zbigniew Jędrzejewski-Szmek 62fe94
index 6105c5131c..48690024f4 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/man/systemd-system.conf.xml
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/man/systemd-system.conf.xml
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -254,7 +254,6 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                                 signal.</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term><varname>TimerSlackNSec=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -281,6 +280,32 @@
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <term><varname>StartTimeoutSec=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <term><varname>StartTimeoutAction=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <term><varname>StartTimeoutRebootArgument=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>Configures an over-all
Zbigniew Jędrzejewski-Szmek 62fe94
+                                system start-up timeout and controls
Zbigniew Jędrzejewski-Szmek 62fe94
+                                what to do when the timeout is
Zbigniew Jędrzejewski-Szmek 62fe94
+                                reached. <varname>StartTimeoutSec=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                specifies the timeout, and defaults to
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <literal>15min</literal>. <varname>StartTimeoutAction=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                configures the action to take when the
Zbigniew Jędrzejewski-Szmek 62fe94
+                                system did not finish boot-up within
Zbigniew Jędrzejewski-Szmek 62fe94
+                                the specified time. It takes the same
Zbigniew Jędrzejewski-Szmek 62fe94
+                                values as the per-service
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <varname>StartLimitAction=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                setting, see
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                for details. Defaults to
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <option>reboot-force</option>. <varname>StartTimeoutRebootArgument=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                configures an optional reboot string
Zbigniew Jędrzejewski-Szmek 62fe94
+                                to pass to the
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                system call.</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                        </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term><varname>DefaultTimerAccuracySec=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <listitem><para>Sets the default
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
Zbigniew Jędrzejewski-Szmek 62fe94
index e584a1f006..20d2a0d755 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/man/systemd.service.xml
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/man/systemd.service.xml
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1155,29 +1155,30 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                         <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <term><varname>FailureAction=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <listitem><para>Configure the action
Zbigniew Jędrzejewski-Szmek 62fe94
+                                to take when the service enters a failed
Zbigniew Jędrzejewski-Szmek 62fe94
+                                state. Takes the same values as
Zbigniew Jędrzejewski-Szmek 62fe94
+                                <varname>StartLimitAction=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                and executes the same actions.
Zbigniew Jędrzejewski-Szmek 62fe94
+                                Defaults to <option>none</option>.
Zbigniew Jędrzejewski-Szmek 62fe94
+                                </para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
+                        </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                        <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <term><varname>RebootArgument=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <listitem><para>Configure the optional
Zbigniew Jędrzejewski-Szmek 62fe94
                                 argument for the
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 system call if
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <varname>StartLimitAction=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
+                                or <varname>FailureAction=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 is a reboot action. This works just
Zbigniew Jędrzejewski-Szmek 62fe94
                                 like the optional argument to
Zbigniew Jędrzejewski-Szmek 62fe94
                                 <command>systemctl reboot</command>
Zbigniew Jędrzejewski-Szmek 62fe94
                                 command.</para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
                         </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                        <varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
-                                <term><varname>FailureAction=</varname></term>
Zbigniew Jędrzejewski-Szmek 62fe94
-                                <listitem><para>Configure the action
Zbigniew Jędrzejewski-Szmek 62fe94
-                                to take when the service enters a failed
Zbigniew Jędrzejewski-Szmek 62fe94
-                                state. Takes the same values as
Zbigniew Jędrzejewski-Szmek 62fe94
-                                <varname>StartLimitAction=</varname>
Zbigniew Jędrzejewski-Szmek 62fe94
-                                and executes the same actions.
Zbigniew Jędrzejewski-Szmek 62fe94
-                                Defaults to <option>none</option>.
Zbigniew Jędrzejewski-Szmek 62fe94
-                                </para></listitem>
Zbigniew Jędrzejewski-Szmek 62fe94
-                        </varlistentry>
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
                 </variablelist>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 <para>Check
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/failure-action.c b/src/core/failure-action.c
Zbigniew Jędrzejewski-Szmek 62fe94
new file mode 100644
Zbigniew Jędrzejewski-Szmek 62fe94
index 0000000000..ca807b68da
Zbigniew Jędrzejewski-Szmek 62fe94
--- /dev/null
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/failure-action.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -0,0 +1,94 @@
Zbigniew Jędrzejewski-Szmek 62fe94
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/***
Zbigniew Jędrzejewski-Szmek 62fe94
+  This file is part of systemd.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  Copyright 2014 Lennart Poettering
Zbigniew Jędrzejewski-Szmek 62fe94
+  Copyright 2012 Michael Olbrich
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is free software; you can redistribute it and/or modify it
Zbigniew Jędrzejewski-Szmek 62fe94
+  under the terms of the GNU Lesser General Public License as published by
Zbigniew Jędrzejewski-Szmek 62fe94
+  the Free Software Foundation; either version 2.1 of the License, or
Zbigniew Jędrzejewski-Szmek 62fe94
+  (at your option) any later version.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is distributed in the hope that it will be useful, but
Zbigniew Jędrzejewski-Szmek 62fe94
+  WITHOUT ANY WARRANTY; without even the implied warranty of
Zbigniew Jędrzejewski-Szmek 62fe94
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Zbigniew Jędrzejewski-Szmek 62fe94
+  Lesser General Public License for more details.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  You should have received a copy of the GNU Lesser General Public License
Zbigniew Jędrzejewski-Szmek 62fe94
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
Zbigniew Jędrzejewski-Szmek 62fe94
+***/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <sys/reboot.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <linux/reboot.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+#include <sys/syscall.h>
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "bus-util.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "bus-error.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "special.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "failure-action.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int failure_action(
Zbigniew Jędrzejewski-Szmek 62fe94
+                Manager *m,
Zbigniew Jędrzejewski-Szmek 62fe94
+                FailureAction action,
Zbigniew Jędrzejewski-Szmek 62fe94
+                const char *reboot_arg) {
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        int r;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(m);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(action >= 0);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(action < _FAILURE_ACTION_MAX);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        switch (action) {
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        case FAILURE_ACTION_NONE:
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        case FAILURE_ACTION_REBOOT: {
Zbigniew Jędrzejewski-Szmek 62fe94
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_warning("Rebooting as result of failure.");
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                update_reboot_param_file(reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+                r = manager_add_job_by_name(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, true, &error, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_error("Failed to reboot: %s.", bus_error_message(&error, r));
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        case FAILURE_ACTION_REBOOT_FORCE:
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_warning("Forcibly rebooting as result of failure.");
Zbigniew Jędrzejewski-Szmek 62fe94
+                update_reboot_param_file(reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+                m->exit_code = MANAGER_REBOOT;
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        case FAILURE_ACTION_REBOOT_IMMEDIATE:
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_warning("Rebooting immediately as result of failure.");
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                sync();
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (reboot_arg) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        log_info("Rebooting with argument '%s'.", reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_info("Rebooting.");
Zbigniew Jędrzejewski-Szmek 62fe94
+                reboot(RB_AUTOBOOT);
Zbigniew Jędrzejewski-Szmek 62fe94
+                break;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        default:
Zbigniew Jędrzejewski-Szmek 62fe94
+                assert_not_reached("Unknown failure action");
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return -ECANCELED;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+static const char* const failure_action_table[_FAILURE_ACTION_MAX] = {
Zbigniew Jędrzejewski-Szmek 62fe94
+        [FAILURE_ACTION_NONE] = "none",
Zbigniew Jędrzejewski-Szmek 62fe94
+        [FAILURE_ACTION_REBOOT] = "reboot",
Zbigniew Jędrzejewski-Szmek 62fe94
+        [FAILURE_ACTION_REBOOT_FORCE] = "reboot-force",
Zbigniew Jędrzejewski-Szmek 62fe94
+        [FAILURE_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate"
Zbigniew Jędrzejewski-Szmek 62fe94
+};
Zbigniew Jędrzejewski-Szmek 62fe94
+DEFINE_STRING_TABLE_LOOKUP(failure_action, FailureAction);
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/failure-action.h b/src/core/failure-action.h
Zbigniew Jędrzejewski-Szmek 62fe94
new file mode 100644
Zbigniew Jędrzejewski-Szmek 62fe94
index 0000000000..5353192f31
Zbigniew Jędrzejewski-Szmek 62fe94
--- /dev/null
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/failure-action.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -0,0 +1,40 @@
Zbigniew Jędrzejewski-Szmek 62fe94
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#pragma once
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+/***
Zbigniew Jędrzejewski-Szmek 62fe94
+  This file is part of systemd.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  Copyright 2014 Lennart Poettering
Zbigniew Jędrzejewski-Szmek 62fe94
+  Copyright 2012 Michael Olbrich
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is free software; you can redistribute it and/or modify it
Zbigniew Jędrzejewski-Szmek 62fe94
+  under the terms of the GNU Lesser General Public License as published by
Zbigniew Jędrzejewski-Szmek 62fe94
+  the Free Software Foundation; either version 2.1 of the License, or
Zbigniew Jędrzejewski-Szmek 62fe94
+  (at your option) any later version.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  systemd is distributed in the hope that it will be useful, but
Zbigniew Jędrzejewski-Szmek 62fe94
+  WITHOUT ANY WARRANTY; without even the implied warranty of
Zbigniew Jędrzejewski-Szmek 62fe94
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Zbigniew Jędrzejewski-Szmek 62fe94
+  Lesser General Public License for more details.
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+  You should have received a copy of the GNU Lesser General Public License
Zbigniew Jędrzejewski-Szmek 62fe94
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
Zbigniew Jędrzejewski-Szmek 62fe94
+***/
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+typedef enum FailureAction {
Zbigniew Jędrzejewski-Szmek 62fe94
+        FAILURE_ACTION_NONE,
Zbigniew Jędrzejewski-Szmek 62fe94
+        FAILURE_ACTION_REBOOT,
Zbigniew Jędrzejewski-Szmek 62fe94
+        FAILURE_ACTION_REBOOT_FORCE,
Zbigniew Jędrzejewski-Szmek 62fe94
+        FAILURE_ACTION_REBOOT_IMMEDIATE,
Zbigniew Jędrzejewski-Szmek 62fe94
+        _FAILURE_ACTION_MAX,
Zbigniew Jędrzejewski-Szmek 62fe94
+        _FAILURE_ACTION_INVALID = -1
Zbigniew Jędrzejewski-Szmek 62fe94
+} FailureAction;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "macro.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "manager.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int failure_action(Manager *m, FailureAction action, const char *reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+const char* failure_action_to_string(FailureAction i) _const_;
Zbigniew Jędrzejewski-Szmek 62fe94
+FailureAction failure_action_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/main.c b/src/core/main.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 792b316c61..ed690162bf 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/main.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/main.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -116,6 +116,9 @@ static FILE* arg_serialization = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
 static bool arg_default_cpu_accounting = false;
Zbigniew Jędrzejewski-Szmek 62fe94
 static bool arg_default_blockio_accounting = false;
Zbigniew Jędrzejewski-Szmek 62fe94
 static bool arg_default_memory_accounting = false;
Zbigniew Jędrzejewski-Szmek 62fe94
+static usec_t arg_start_timeout_usec = DEFAULT_MANAGER_START_TIMEOUT_USEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+static FailureAction arg_start_timeout_action = FAILURE_ACTION_REBOOT_FORCE;
Zbigniew Jędrzejewski-Szmek 62fe94
+static char *arg_start_timeout_reboot_arg = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static void nop_handler(int sig) {}
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -669,6 +672,9 @@ static int parse_config_file(void) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 { "Manager", "DefaultCPUAccounting",      config_parse_bool,             0, &arg_default_cpu_accounting            },
Zbigniew Jędrzejewski-Szmek 62fe94
                 { "Manager", "DefaultBlockIOAccounting",  config_parse_bool,             0, &arg_default_blockio_accounting        },
Zbigniew Jędrzejewski-Szmek 62fe94
                 { "Manager", "DefaultMemoryAccounting",   config_parse_bool,             0, &arg_default_memory_accounting         },
Zbigniew Jędrzejewski-Szmek 62fe94
+                { "Manager", "StartTimeoutSec",           config_parse_sec,              0, &arg_start_timeout_usec                },
Zbigniew Jędrzejewski-Szmek 62fe94
+                { "Manager", "StartTimeoutAction",        config_parse_failure_action,   0, &arg_start_timeout_action              },
Zbigniew Jędrzejewski-Szmek 62fe94
+                { "Manager", "StartTimeoutRebootArgument",config_parse_string,           0, &arg_start_timeout_reboot_arg          },
Zbigniew Jędrzejewski-Szmek 62fe94
                 {}
Zbigniew Jędrzejewski-Szmek 62fe94
         };
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1628,6 +1634,10 @@ int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 62fe94
         m->default_memory_accounting = arg_default_memory_accounting;
Zbigniew Jędrzejewski-Szmek 62fe94
         m->runtime_watchdog = arg_runtime_watchdog;
Zbigniew Jędrzejewski-Szmek 62fe94
         m->shutdown_watchdog = arg_shutdown_watchdog;
Zbigniew Jędrzejewski-Szmek 62fe94
+        m->start_timeout_usec = arg_start_timeout_usec;
Zbigniew Jędrzejewski-Szmek 62fe94
+        m->start_timeout_action = arg_start_timeout_action;
Zbigniew Jędrzejewski-Szmek 62fe94
+        free_and_strdup(&m->start_timeout_reboot_arg, arg_start_timeout_reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         m->userspace_timestamp = userspace_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
         m->kernel_timestamp = kernel_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
         m->initrd_timestamp = initrd_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1816,6 +1826,9 @@ finish:
Zbigniew Jędrzejewski-Szmek 62fe94
         set_free(arg_syscall_archs);
Zbigniew Jędrzejewski-Szmek 62fe94
         arg_syscall_archs = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(arg_start_timeout_reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+        arg_start_timeout_reboot_arg = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         label_finish();
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (reexecute) {
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/manager.c b/src/core/manager.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 7401817844..1bb0c9025f 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/manager.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/manager.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -435,6 +435,8 @@ int manager_new(SystemdRunningAs running_as, bool test_run, Manager **_m) {
Zbigniew Jędrzejewski-Szmek 62fe94
         m->running_as = running_as;
Zbigniew Jędrzejewski-Szmek 62fe94
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
Zbigniew Jędrzejewski-Szmek 62fe94
         m->default_timer_accuracy_usec = USEC_PER_MINUTE;
Zbigniew Jędrzejewski-Szmek 62fe94
+        m->start_timeout_usec = DEFAULT_MANAGER_START_TIMEOUT_USEC;
Zbigniew Jędrzejewski-Szmek 62fe94
+        m->start_timeout_action = FAILURE_ACTION_REBOOT_FORCE;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -823,6 +825,9 @@ void manager_free(Manager *m) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         manager_close_idle_pipe(m);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_event_source_unref(m->start_timeout_event_source);
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(m->start_timeout_reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         udev_unref(m->udev);
Zbigniew Jędrzejewski-Szmek 62fe94
         sd_event_unref(m->event);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -970,6 +975,20 @@ static int manager_distribute_fds(Manager *m, FDSet *fds) {
Zbigniew Jędrzejewski-Szmek 62fe94
         return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+static int on_start_timeout(sd_event_source *s, usec_t usec, void *userdata) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        Manager *m = userdata;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(m);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        m->start_timeout_event_source = sd_event_source_unref(m->start_timeout_event_source);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_error("Startup timed out.");
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        failure_action(m, m->start_timeout_action, m->start_timeout_reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
Zbigniew Jędrzejewski-Szmek 62fe94
         int r, q;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1042,6 +1061,22 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
Zbigniew Jędrzejewski-Szmek 62fe94
                 m->send_reloading_done = true;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* Possibly set up a start timeout */
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (!dual_timestamp_is_set(&m->finish_timestamp)) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                m->start_timeout_event_source = sd_event_source_unref(m->start_timeout_event_source);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (m->start_timeout_usec) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                        r = sd_event_add_time(
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        m->event,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        &m->start_timeout_event_source,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        CLOCK_MONOTONIC,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        now(CLOCK_MONOTONIC) + m->start_timeout_usec, 0,
Zbigniew Jędrzejewski-Szmek 62fe94
+                                        on_start_timeout, m);
Zbigniew Jędrzejewski-Szmek 62fe94
+                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
+                                log_error("Failed to add start timeout event: %s", strerror(-r));
Zbigniew Jędrzejewski-Szmek 62fe94
+                }
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         return r;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2462,10 +2497,8 @@ void manager_check_finished(Manager *m) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (hashmap_size(m->jobs) > 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-                if (m->jobs_in_progress_event_source) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                        sd_event_source_set_time(m->jobs_in_progress_event_source,
Zbigniew Jędrzejewski-Szmek 62fe94
-                                                 now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
Zbigniew Jędrzejewski-Szmek 62fe94
-                }
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (m->jobs_in_progress_event_source)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        sd_event_source_set_time(m->jobs_in_progress_event_source, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 return;
Zbigniew Jędrzejewski-Szmek 62fe94
         }
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2487,6 +2520,8 @@ void manager_check_finished(Manager *m) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         dual_timestamp_get(&m->finish_timestamp);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+        m->start_timeout_event_source = sd_event_source_unref(m->start_timeout_event_source);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         if (m->running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
                 /* Note that m->kernel_usec.monotonic is always at 0,
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/manager.h b/src/core/manager.h
Zbigniew Jędrzejewski-Szmek 62fe94
index 7cb76f7f00..7d26c3adea 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/manager.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/manager.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -33,6 +33,8 @@
Zbigniew Jędrzejewski-Szmek 62fe94
 /* Enforce upper limit how many names we allow */
Zbigniew Jędrzejewski-Szmek 62fe94
 #define MANAGER_MAX_NAMES 131072 /* 128K */
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
+#define DEFAULT_MANAGER_START_TIMEOUT_USEC (15*USEC_PER_MINUTE)
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
 typedef struct Manager Manager;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 typedef enum ManagerState {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -69,6 +71,7 @@ typedef enum ManagerExitCode {
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "unit-name.h"
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "exit-status.h"
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "show-status.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "failure-action.h"
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 struct Manager {
Zbigniew Jędrzejewski-Szmek 62fe94
         /* Note that the set of units we know of is allowed to be
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -152,6 +155,7 @@ struct Manager {
Zbigniew Jędrzejewski-Szmek 62fe94
         dual_timestamp initrd_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
         dual_timestamp userspace_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
         dual_timestamp finish_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
         dual_timestamp security_start_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
         dual_timestamp security_finish_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
         dual_timestamp generators_start_timestamp;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -279,6 +283,12 @@ struct Manager {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         /* Used for processing polkit authorization responses */
Zbigniew Jędrzejewski-Szmek 62fe94
         Hashmap *polkit_registry;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* System wide startup timeouts */
Zbigniew Jędrzejewski-Szmek 62fe94
+        usec_t start_timeout_usec;
Zbigniew Jędrzejewski-Szmek 62fe94
+        sd_event_source *start_timeout_event_source;
Zbigniew Jędrzejewski-Szmek 62fe94
+        FailureAction start_timeout_action;
Zbigniew Jędrzejewski-Szmek 62fe94
+        char *start_timeout_reboot_arg;
Zbigniew Jędrzejewski-Szmek 62fe94
 };
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 int manager_new(SystemdRunningAs running_as, bool test_run, Manager **m);
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/service.c b/src/core/service.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 1b864c4c8c..223e4b3a41 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/service.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/service.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -23,9 +23,6 @@
Zbigniew Jędrzejewski-Szmek 62fe94
 #include <signal.h>
Zbigniew Jędrzejewski-Szmek 62fe94
 #include <dirent.h>
Zbigniew Jędrzejewski-Szmek 62fe94
 #include <unistd.h>
Zbigniew Jędrzejewski-Szmek 62fe94
-#include <sys/reboot.h>
Zbigniew Jędrzejewski-Szmek 62fe94
-#include <linux/reboot.h>
Zbigniew Jędrzejewski-Szmek 62fe94
-#include <sys/syscall.h>
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "async.h"
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "manager.h"
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1052,8 +1049,6 @@ static int cgroup_good(Service *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
         return !r;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-static int service_execute_action(Service *s, FailureAction action, const char *reason, bool log_action_none);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
 static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) {
Zbigniew Jędrzejewski-Szmek 62fe94
         int r;
Zbigniew Jędrzejewski-Szmek 62fe94
         assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1063,8 +1058,10 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        if (s->result != SERVICE_SUCCESS)
Zbigniew Jędrzejewski-Szmek 62fe94
-                service_execute_action(s, s->failure_action, "failed", false);
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (s->result != SERVICE_SUCCESS) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                log_warning_unit(UNIT(s)->id, "%s failed.", UNIT(s)->id);
Zbigniew Jędrzejewski-Szmek 62fe94
+                failure_action(UNIT(s)->manager, s->failure_action, s->reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
+        }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (allow_restart &&
Zbigniew Jędrzejewski-Szmek 62fe94
             !s->forbid_restart &&
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -1601,67 +1598,15 @@ fail:
Zbigniew Jędrzejewski-Szmek 62fe94
         service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-static int service_execute_action(Service *s, FailureAction action, const char *reason, bool log_action_none) {
Zbigniew Jędrzejewski-Szmek 62fe94
-        assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        if (action == SERVICE_FAILURE_ACTION_REBOOT ||
Zbigniew Jędrzejewski-Szmek 62fe94
-            action == SERVICE_FAILURE_ACTION_REBOOT_FORCE)
Zbigniew Jędrzejewski-Szmek 62fe94
-                update_reboot_param_file(s->reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        switch (action) {
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        case SERVICE_FAILURE_ACTION_NONE:
Zbigniew Jędrzejewski-Szmek 62fe94
-                if (log_action_none)
Zbigniew Jędrzejewski-Szmek 62fe94
-                        log_warning_unit(UNIT(s)->id, "%s %s, refusing to start.", UNIT(s)->id, reason);
Zbigniew Jędrzejewski-Szmek 62fe94
-                break;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        case SERVICE_FAILURE_ACTION_REBOOT: {
Zbigniew Jędrzejewski-Szmek 62fe94
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
-                int r;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-                log_warning_unit(UNIT(s)->id, "%s %s, rebooting.", UNIT(s)->id, reason);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-                r = manager_add_job_by_name(UNIT(s)->manager, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, true, &error, NULL);
Zbigniew Jędrzejewski-Szmek 62fe94
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 62fe94
-                        log_error_unit(UNIT(s)->id, "Failed to reboot: %s.", bus_error_message(&error, r));
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-                break;
Zbigniew Jędrzejewski-Szmek 62fe94
-        }
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        case SERVICE_FAILURE_ACTION_REBOOT_FORCE:
Zbigniew Jędrzejewski-Szmek 62fe94
-                log_warning_unit(UNIT(s)->id, "%s %s, forcibly rebooting.", UNIT(s)->id, reason);
Zbigniew Jędrzejewski-Szmek 62fe94
-                UNIT(s)->manager->exit_code = MANAGER_REBOOT;
Zbigniew Jędrzejewski-Szmek 62fe94
-                break;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        case SERVICE_FAILURE_ACTION_REBOOT_IMMEDIATE:
Zbigniew Jędrzejewski-Szmek 62fe94
-                log_warning_unit(UNIT(s)->id, "%s %s, rebooting immediately.", UNIT(s)->id, reason);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-                sync();
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-                if (s->reboot_arg) {
Zbigniew Jędrzejewski-Szmek 62fe94
-                        log_info("Rebooting with argument '%s'.", s->reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
-                        syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, s->reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
-                }
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-                log_info("Rebooting.");
Zbigniew Jędrzejewski-Szmek 62fe94
-                reboot(RB_AUTOBOOT);
Zbigniew Jędrzejewski-Szmek 62fe94
-                break;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        default:
Zbigniew Jędrzejewski-Szmek 62fe94
-                log_error_unit(UNIT(s)->id, "failure action=%i", action);
Zbigniew Jędrzejewski-Szmek 62fe94
-                assert_not_reached("Unknown FailureAction.");
Zbigniew Jędrzejewski-Szmek 62fe94
-        }
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-        return -ECANCELED;
Zbigniew Jędrzejewski-Szmek 62fe94
-}
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
 static int service_start_limit_test(Service *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
         assert(s);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         if (ratelimit_test(&s->start_limit))
Zbigniew Jędrzejewski-Szmek 62fe94
                 return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        return service_execute_action(s, s->start_limit_action, "start request repeated too quickly", true);
Zbigniew Jędrzejewski-Szmek 62fe94
+        log_warning_unit(UNIT(s)->id, "start request repeated too quickly for %s", UNIT(s)->id);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return failure_action(UNIT(s)->manager, s->start_limit_action, s->reboot_arg);
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 static int service_start(Unit *u) {
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -2908,14 +2853,6 @@ static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-static const char* const failure_action_table[_SERVICE_FAILURE_ACTION_MAX] = {
Zbigniew Jędrzejewski-Szmek 62fe94
-        [SERVICE_FAILURE_ACTION_NONE] = "none",
Zbigniew Jędrzejewski-Szmek 62fe94
-        [SERVICE_FAILURE_ACTION_REBOOT] = "reboot",
Zbigniew Jędrzejewski-Szmek 62fe94
-        [SERVICE_FAILURE_ACTION_REBOOT_FORCE] = "reboot-force",
Zbigniew Jędrzejewski-Szmek 62fe94
-        [SERVICE_FAILURE_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate"
Zbigniew Jędrzejewski-Szmek 62fe94
-};
Zbigniew Jędrzejewski-Szmek 62fe94
-DEFINE_STRING_TABLE_LOOKUP(failure_action, FailureAction);
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
 const UnitVTable service_vtable = {
Zbigniew Jędrzejewski-Szmek 62fe94
         .object_size = sizeof(Service),
Zbigniew Jędrzejewski-Szmek 62fe94
         .exec_context_offset = offsetof(Service, exec_context),
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/service.h b/src/core/service.h
Zbigniew Jędrzejewski-Szmek 62fe94
index 0227321d99..5bcfd14339 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/service.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/service.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -28,6 +28,7 @@ typedef struct Service Service;
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "ratelimit.h"
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "kill.h"
Zbigniew Jędrzejewski-Szmek 62fe94
 #include "exit-status.h"
Zbigniew Jędrzejewski-Szmek 62fe94
+#include "failure-action.h"
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 typedef enum ServiceState {
Zbigniew Jędrzejewski-Szmek 62fe94
         SERVICE_DEAD,
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -113,15 +114,6 @@ typedef enum ServiceResult {
Zbigniew Jędrzejewski-Szmek 62fe94
         _SERVICE_RESULT_INVALID = -1
Zbigniew Jędrzejewski-Szmek 62fe94
 } ServiceResult;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-typedef enum FailureAction {
Zbigniew Jędrzejewski-Szmek 62fe94
-        SERVICE_FAILURE_ACTION_NONE,
Zbigniew Jędrzejewski-Szmek 62fe94
-        SERVICE_FAILURE_ACTION_REBOOT,
Zbigniew Jędrzejewski-Szmek 62fe94
-        SERVICE_FAILURE_ACTION_REBOOT_FORCE,
Zbigniew Jędrzejewski-Szmek 62fe94
-        SERVICE_FAILURE_ACTION_REBOOT_IMMEDIATE,
Zbigniew Jędrzejewski-Szmek 62fe94
-        _SERVICE_FAILURE_ACTION_MAX,
Zbigniew Jędrzejewski-Szmek 62fe94
-        _SERVICE_FAILURE_ACTION_INVALID = -1
Zbigniew Jędrzejewski-Szmek 62fe94
-} FailureAction;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
 struct Service {
Zbigniew Jędrzejewski-Szmek 62fe94
         Unit meta;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -193,10 +185,9 @@ struct Service {
Zbigniew Jędrzejewski-Szmek 62fe94
         char *status_text;
Zbigniew Jędrzejewski-Szmek 62fe94
         int status_errno;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
-        FailureAction failure_action;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
         RateLimit start_limit;
Zbigniew Jędrzejewski-Szmek 62fe94
         FailureAction start_limit_action;
Zbigniew Jędrzejewski-Szmek 62fe94
+        FailureAction failure_action;
Zbigniew Jędrzejewski-Szmek 62fe94
         char *reboot_arg;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         UnitRef accept_socket;
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -234,6 +225,3 @@ NotifyState notify_state_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 const char* service_result_to_string(ServiceResult i) _const_;
Zbigniew Jędrzejewski-Szmek 62fe94
 ServiceResult service_result_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
-
Zbigniew Jędrzejewski-Szmek 62fe94
-const char* failure_action_to_string(FailureAction i) _const_;
Zbigniew Jędrzejewski-Szmek 62fe94
-FailureAction failure_action_from_string(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/core/system.conf b/src/core/system.conf
Zbigniew Jędrzejewski-Szmek 62fe94
index 65a35a0689..45448de328 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/core/system.conf
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/core/system.conf
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -23,6 +23,9 @@
Zbigniew Jędrzejewski-Szmek 62fe94
 #CapabilityBoundingSet=
Zbigniew Jędrzejewski-Szmek 62fe94
 #SystemCallArchitectures=
Zbigniew Jędrzejewski-Szmek 62fe94
 #TimerSlackNSec=
Zbigniew Jędrzejewski-Szmek 62fe94
+#StartTimeoutSec=15min
Zbigniew Jędrzejewski-Szmek 62fe94
+#StartTimeoutAction=reboot-force
Zbigniew Jędrzejewski-Szmek 62fe94
+#StartTimeoutRebootArgument=
Zbigniew Jędrzejewski-Szmek 62fe94
 #DefaultTimerAccuracySec=1min
Zbigniew Jędrzejewski-Szmek 62fe94
 #DefaultStandardOutput=journal
Zbigniew Jędrzejewski-Szmek 62fe94
 #DefaultStandardError=inherit
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/shared/util.c b/src/shared/util.c
Zbigniew Jędrzejewski-Szmek 62fe94
index a54e879953..fc6f668726 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/shared/util.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/shared/util.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -7137,3 +7137,24 @@ int unquote_many_words(const char **p, ...) {
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
         return c;
Zbigniew Jędrzejewski-Szmek 62fe94
 }
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int free_and_strdup(char **p, const char *s) {
Zbigniew Jędrzejewski-Szmek 62fe94
+        char *t;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        assert(p);
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        /* Replaces a string pointer with an strdup()ed new string,
Zbigniew Jędrzejewski-Szmek 62fe94
+         * possibly freeing the old one. */
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        if (s) {
Zbigniew Jędrzejewski-Szmek 62fe94
+                t = strdup(s);
Zbigniew Jędrzejewski-Szmek 62fe94
+                if (!t)
Zbigniew Jędrzejewski-Szmek 62fe94
+                        return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 62fe94
+        } else
Zbigniew Jędrzejewski-Szmek 62fe94
+                t = NULL;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        free(*p);
Zbigniew Jędrzejewski-Szmek 62fe94
+        *p = t;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+        return 0;
Zbigniew Jędrzejewski-Szmek 62fe94
+}
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/shared/util.h b/src/shared/util.h
Zbigniew Jędrzejewski-Szmek 62fe94
index 8cd47b8294..cd947dbbef 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/shared/util.h
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/shared/util.h
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -978,3 +978,5 @@ int is_symlink(const char *path);
Zbigniew Jędrzejewski-Szmek 62fe94
 
Zbigniew Jędrzejewski-Szmek 62fe94
 int unquote_first_word(const char **p, char **ret);
Zbigniew Jędrzejewski-Szmek 62fe94
 int unquote_many_words(const char **p, ...) _sentinel_;
Zbigniew Jędrzejewski-Szmek 62fe94
+
Zbigniew Jędrzejewski-Szmek 62fe94
+int free_and_strdup(char **p, const char *s);
Zbigniew Jędrzejewski-Szmek 62fe94
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
Zbigniew Jędrzejewski-Szmek 62fe94
index 88e7d10c60..58fe4433b7 100644
Zbigniew Jędrzejewski-Szmek 62fe94
--- a/src/test/test-tables.c
Zbigniew Jędrzejewski-Szmek 62fe94
+++ b/src/test/test-tables.c
Zbigniew Jędrzejewski-Szmek 62fe94
@@ -63,7 +63,7 @@ int main(int argc, char **argv) {
Zbigniew Jędrzejewski-Szmek 62fe94
         test_table(device_state, DEVICE_STATE);
Zbigniew Jędrzejewski-Szmek 62fe94
         test_table(exec_input, EXEC_INPUT);
Zbigniew Jędrzejewski-Szmek 62fe94
         test_table(exec_output, EXEC_OUTPUT);
Zbigniew Jędrzejewski-Szmek 62fe94
-        test_table(failure_action, SERVICE_FAILURE_ACTION);
Zbigniew Jędrzejewski-Szmek 62fe94
+        test_table(failure_action, FAILURE_ACTION);
Zbigniew Jędrzejewski-Szmek 62fe94
         test_table(job_mode, JOB_MODE);
Zbigniew Jędrzejewski-Szmek 62fe94
         test_table(job_result, JOB_RESULT);
Zbigniew Jędrzejewski-Szmek 62fe94
         test_table(job_state, JOB_STATE);