]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: Add systemd.crash_action= kernel command line argument
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 29 Apr 2024 06:46:58 +0000 (08:46 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 29 Apr 2024 12:34:22 +0000 (14:34 +0200)
Required for integration tests to power off on PID 1 crashes. We
deprecate systemd.crash_reboot and related options by removing them
from the documentation but still parsing them.

NEWS
man/kernel-command-line.xml
man/systemd-system.conf.xml
man/systemd.xml
src/basic/getopt-defs.h
src/core/crash-handler.c
src/core/main.c
src/core/main.h
src/core/system.conf.in
test/fuzz/fuzz-unit-file/directives-all.service

diff --git a/NEWS b/NEWS
index 42027a4c8f150ed5d335550a1f81d7bd33ab1736..566ee2a9d55c04f5ab81dc7e26b66e025630030e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -66,6 +66,9 @@ CHANGES WITH 256-rc1:
           'D' stanzas. For example, with the combination of 'R /foo' and 'x
           /foo/bar', /foo/bar will now be excluded from removal.
 
+        * systemd.crash_reboot and related settings are deprecated in favor of
+          systemd.crash_action=.
+
         General Changes and New Features:
 
         * Various programs will now attempt to load the main configuration file
@@ -251,6 +254,10 @@ CHANGES WITH 256-rc1:
           that have /usr/bin/ and /usr/sbin/ separate. It's generally
           recommended to make the latter a symlink to the former these days.
 
+        * A new systemd.crash_action= kernel command line option has been added
+          that configures what to do after the system manager (PID 1) crashes.
+          This can also be configured through CrashAction= in systemd.conf.
+
         Journal:
 
         * systemd-journald can now forward journal entries to a socket
index 28250a2720b0d1933565f759cd6ad8ffe78f2798..3dd5449bd06d22e05204791fef8467a924ef10b8 100644 (file)
@@ -54,7 +54,7 @@
         <term><varname>systemd.dump_core</varname></term>
         <term><varname>systemd.crash_chvt</varname></term>
         <term><varname>systemd.crash_shell</varname></term>
-        <term><varname>systemd.crash_reboot</varname></term>
+        <term><varname>systemd.crash_action=</varname></term>
         <term><varname>systemd.confirm_spawn</varname></term>
         <term><varname>systemd.service_watchdogs</varname></term>
         <term><varname>systemd.show_status</varname></term>
index 88f13d05b61c58877a090c6f7b6b3ec1f711fc64..ae5b61b1493ddfef463b5f6064027aada24ad2c6 100644 (file)
@@ -78,7 +78,7 @@
         <term><varname>DumpCore=yes</varname></term>
         <term><varname>CrashChangeVT=no</varname></term>
         <term><varname>CrashShell=no</varname></term>
-        <term><varname>CrashReboot=no</varname></term>
+        <term><varname>CrashAction=freeze</varname></term>
         <term><varname>ShowStatus=yes</varname></term>
         <term><varname>DefaultStandardOutput=journal</varname></term>
         <term><varname>DefaultStandardError=inherit</varname></term>
index df0027886c3b8817aa75821dd3e0ad0fe15c6adb..66db5bbf2507f45257d9ad78d15726464172a6a3 100644 (file)
       </varlistentry>
 
       <varlistentry>
-        <term><varname>systemd.crash_reboot</varname></term>
+        <term><varname>systemd.crash_action=</varname></term>
 
-        <listitem><para>Takes a boolean argument or enables the option if specified
-        without an argument. If enabled, the system manager (PID 1) will reboot the
-        machine automatically when it crashes, after a 10s delay.  Otherwise, the
-        system will hang indefinitely. Defaults to disabled, in order to avoid a
-        reboot loop. If combined with <varname>systemd.crash_shell</varname>, the
-        system is rebooted after the shell exits.</para>
+        <listitem><para>Takes one of <literal>freeze</literal>, <literal>reboot</literal> or
+        <literal>poweroff</literal>. Defaults to <literal>freeze</literal>. If set to
+        <literal>freeze</literal>, the system will hang indefinitely when the system manager (PID 1) crashes.
+        If set to <literal>reboot</literal>, the system manager (PID 1) will reboot the machine automatically
+        when it crashes, after a 10s delay. If set to <literal>poweroff</literal>, the system manager (PID 1)
+        will power off the machine immediately when it crashes. If combined with
+        <varname>systemd.crash_shell</varname>, the configured crash action is executed after the shell
+        exits.</para>
 
-        <xi:include href="version-info.xml" xpointer="v227"/></listitem>
+        <xi:include href="version-info.xml" xpointer="v256"/></listitem>
       </varlistentry>
 
       <varlistentry>
         </varlistentry>
 
         <varlistentry>
-          <term><option>--crash-reboot</option></term>
+          <term><option>--crash-action=</option></term>
 
-          <listitem><para>Automatically reboot the system on crash. This switch has no effect when running as
-          user instance. See <varname>systemd.crash_reboot</varname> above.</para>
+          <listitem><para>Specify what to do when the system manager (PID 1) crashes. This switch has no
+          effect when systemd is running as user instance. See <varname>systemd.crash_action=</varname>
+          above.</para>
 
-          <xi:include href="version-info.xml" xpointer="v227"/></listitem>
+          <xi:include href="version-info.xml" xpointer="v256"/></listitem>
         </varlistentry>
 
         <varlistentry>
index 3efeb6df80f1214d8f168c881b26121eba4808eb..9abef6f156699b4f87ef3e78a1cb4fbfe5803920 100644 (file)
@@ -26,6 +26,7 @@
         ARG_CRASH_CHVT,                         \
         ARG_CRASH_SHELL,                        \
         ARG_CRASH_REBOOT,                       \
+        ARG_CRASH_ACTION,                       \
         ARG_CONFIRM_SPAWN,                      \
         ARG_SHOW_STATUS,                        \
         ARG_DESERIALIZE,                        \
@@ -61,6 +62,7 @@
         { "crash-chvt",               required_argument, NULL, ARG_CRASH_CHVT               }, \
         { "crash-shell",              optional_argument, NULL, ARG_CRASH_SHELL              }, \
         { "crash-reboot",             optional_argument, NULL, ARG_CRASH_REBOOT             }, \
+        { "crash-action",             required_argument, NULL, ARG_CRASH_ACTION             }, \
         { "confirm-spawn",            optional_argument, NULL, ARG_CONFIRM_SPAWN            }, \
         { "show-status",              optional_argument, NULL, ARG_SHOW_STATUS              }, \
         { "deserialize",              required_argument, NULL, ARG_DESERIALIZE              }, \
index f5c31b6b7483469cf93c617d0321e9a8b58da10c..4a3fc017fabd267dafd5bc04924a4d360da86eb3 100644 (file)
@@ -27,7 +27,13 @@ _noreturn_ void freeze_or_exit_or_reboot(void) {
                 _exit(EXIT_EXCEPTION);
         }
 
-        if (arg_crash_reboot) {
+        if (arg_crash_action == CRASH_POWEROFF) {
+                log_notice("Shutting down...");
+                (void) reboot(RB_POWER_OFF);
+                log_struct_errno(LOG_EMERG, errno,
+                                 LOG_MESSAGE("Failed to power off: %m"),
+                                 "MESSAGE_ID=" SD_MESSAGE_CRASH_FAILED_STR);
+        } else if (arg_crash_action == CRASH_REBOOT) {
                 log_notice("Rebooting in 10s...");
                 (void) sleep(10);
 
index 7362a6a82205491b7d4f1634f601a37d780e72ae..f3a40f65bb8065d76b53ffd2b098a9d98bfa2118 100644 (file)
@@ -88,6 +88,7 @@
 #include "special.h"
 #include "stat-util.h"
 #include "stdio-util.h"
+#include "string-table.h"
 #include "strv.h"
 #include "switch-root.h"
 #include "sysctl-util.h"
@@ -122,7 +123,7 @@ static RuntimeScope arg_runtime_scope;
 bool arg_dump_core;
 int arg_crash_chvt;
 bool arg_crash_shell;
-bool arg_crash_reboot;
+CrashAction arg_crash_action;
 static char *arg_confirm_spawn;
 static ShowStatus arg_show_status;
 static StatusUnitFormat arg_status_unit_format;
@@ -161,6 +162,16 @@ static char **saved_env = NULL;
 static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
                                const struct rlimit *saved_rlimit_memlock);
 
+static const char* const crash_action_table[_CRASH_ACTION_MAX] = {
+        [CRASH_FREEZE]   = "freeze",
+        [CRASH_REBOOT]   = "reboot",
+        [CRASH_POWEROFF] = "poweroff",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(crash_action, CrashAction);
+
+static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_crash_action, crash_action, CrashAction, CRASH_FREEZE, "Invalid crash action");
+
 static int manager_find_user_config_paths(char ***ret_files, char ***ret_dirs) {
         _cleanup_free_ char *base = NULL;
         _cleanup_strv_free_ char **files = NULL, **dirs = NULL;
@@ -279,7 +290,18 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                 if (r < 0)
                         log_warning_errno(r, "Failed to parse crash reboot switch %s, ignoring: %m", value);
                 else
-                        arg_crash_reboot = r;
+                        arg_crash_action = r ? CRASH_REBOOT : CRASH_FREEZE;
+
+        } else if (proc_cmdline_key_streq(key, "systemd.crash_action")) {
+
+                if (proc_cmdline_value_missing(key, value))
+                        return 0;
+
+                r = crash_action_from_string(value);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to parse crash action switch %s, ignoring: %m", value);
+                else
+                        arg_crash_action = r;
 
         } else if (proc_cmdline_key_streq(key, "systemd.confirm_spawn")) {
                 char *s;
@@ -653,6 +675,36 @@ static int config_parse_protect_system_pid1(
         return 0;
 }
 
+static int config_parse_crash_reboot(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        CrashAction *v = ASSERT_PTR(data);
+        int r;
+
+        if (isempty(rvalue)) {
+                *v = CRASH_REBOOT;
+                return 0;
+        }
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse CrashReboot= argument '%s', ignoring: %m", rvalue);
+                return 0;
+        }
+
+        *v = r > 0 ? CRASH_REBOOT : CRASH_FREEZE;
+        return 0;
+}
+
 static int parse_config_file(void) {
         const ConfigTableItem items[] = {
                 { "Manager", "LogLevel",                     config_parse_level2,                0,                        NULL                              },
@@ -664,7 +716,8 @@ static int parse_config_file(void) {
                 { "Manager", "CrashChVT", /* legacy */       config_parse_crash_chvt,            0,                        &arg_crash_chvt                   },
                 { "Manager", "CrashChangeVT",                config_parse_crash_chvt,            0,                        &arg_crash_chvt                   },
                 { "Manager", "CrashShell",                   config_parse_bool,                  0,                        &arg_crash_shell                  },
-                { "Manager", "CrashReboot",                  config_parse_bool,                  0,                        &arg_crash_reboot                 },
+                { "Manager", "CrashReboot",                  config_parse_crash_reboot,          0,                        &arg_crash_action                 },
+                { "Manager", "CrashAction",                  config_parse_crash_action,          0,                        &arg_crash_action                 },
                 { "Manager", "ShowStatus",                   config_parse_show_status,           0,                        &arg_show_status                  },
                 { "Manager", "StatusUnitFormat",             config_parse_status_unit_format,    0,                        &arg_status_unit_format           },
                 { "Manager", "CPUAffinity",                  config_parse_cpu_affinity2,         0,                        &arg_cpu_affinity                 },
@@ -980,9 +1033,17 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_CRASH_REBOOT:
-                        r = parse_boolean_argument("--crash-reboot", optarg, &arg_crash_reboot);
+                        r = parse_boolean_argument("--crash-reboot", optarg, NULL);
                         if (r < 0)
                                 return r;
+                        arg_crash_action = r > 0 ? CRASH_REBOOT : CRASH_FREEZE;
+                        break;
+
+                case ARG_CRASH_ACTION:
+                        r = crash_action_from_string(optarg);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse crash action \"%s\": %m", optarg);
+                        arg_crash_action = r;
                         break;
 
                 case ARG_CONFIRM_SPAWN:
@@ -1098,7 +1159,7 @@ static int help(void) {
                "     --unit=UNIT                 Set default unit\n"
                "     --dump-core[=BOOL]          Dump core on crash\n"
                "     --crash-vt=NR               Change to specified VT on crash\n"
-               "     --crash-reboot[=BOOL]       Reboot on crash\n"
+               "     --crash-action=ACTION       Specify what to do on crash\n"
                "     --crash-shell[=BOOL]        Run shell on crash\n"
                "     --confirm-spawn[=BOOL]      Ask for confirmation when spawning processes\n"
                "     --show-status[=BOOL]        Show status updates on the console during boot\n"
@@ -2590,7 +2651,7 @@ static void reset_arguments(void) {
         arg_dump_core = true;
         arg_crash_chvt = -1;
         arg_crash_shell = false;
-        arg_crash_reboot = false;
+        arg_crash_action = CRASH_FREEZE;
         arg_confirm_spawn = mfree(arg_confirm_spawn);
         arg_show_status = _SHOW_STATUS_INVALID;
         arg_status_unit_format = STATUS_UNIT_FORMAT_DEFAULT;
index b12a1ccfd781f54c014dbe3a93daf289f52cc76b..1949a08588905cf0aa0ff6bc590c3578be64e96c 100644 (file)
@@ -1,9 +1,21 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <errno.h>
 #include <stdbool.h>
 
+typedef enum CrashAction {
+        CRASH_FREEZE,
+        CRASH_REBOOT,
+        CRASH_POWEROFF,
+        _CRASH_ACTION_MAX,
+        _CRASH_ACTION_INVALID = -EINVAL,
+} CrashAction;
+
+const char* crash_action_to_string(CrashAction action);
+CrashAction crash_action_from_string(const char *action);
+
 extern bool arg_dump_core;
 extern int arg_crash_chvt;
 extern bool arg_crash_shell;
-extern bool arg_crash_reboot;
+extern CrashAction arg_crash_action;
index 9b89a6aa77d7ce030a5614cf3c4a6853c263dd67..1c08aa4d22da745bc398327d601354bf8338085b 100644 (file)
@@ -26,7 +26,7 @@
 #ShowStatus=yes
 #CrashChangeVT=no
 #CrashShell=no
-#CrashReboot=no
+#CrashAction=freeze
 #CtrlAltDelBurstAction=reboot-force
 #CPUAffinity=
 #NUMAPolicy=default
index 670e589babe7a22665e090071f4d280dfa0845ad..dbd56ec752fda748b065c8b6c600d617cd42c23a 100644 (file)
@@ -706,6 +706,7 @@ CPUAffinity=
 CapabilityBoundingSet=
 CrashChangeVT=
 CrashReboot=
+CrashAction=
 CrashShell=
 CtrlAltDelBurstAction=
 DefaultBlockIOAccounting=