core: Add systemd.crash_action= kernel command line argument

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.
This commit is contained in:
Daan De Meyer
2024-04-29 08:46:58 +02:00
parent 821bf13b6e
commit 7a66f21556
10 changed files with 115 additions and 23 deletions

7
NEWS
View File

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

View 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>

View 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>

View File

@@ -853,16 +853,18 @@
</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>
@@ -1390,12 +1392,13 @@
</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>

View 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 }, \

View 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);

View 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;

View 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;

View File

@@ -26,7 +26,7 @@
#ShowStatus=yes
#CrashChangeVT=no
#CrashShell=no
#CrashReboot=no
#CrashAction=freeze
#CtrlAltDelBurstAction=reboot-force
#CPUAffinity=
#NUMAPolicy=default

View File

@@ -706,6 +706,7 @@ CPUAffinity=
CapabilityBoundingSet=
CrashChangeVT=
CrashReboot=
CrashAction=
CrashShell=
CtrlAltDelBurstAction=
DefaultBlockIOAccounting=