core: introduce systemd.early_core_pattern= kernel cmdline option

Until a core dump handler is installed by systemd-sysctl, the generation of
core dump for services is turned OFF which can make the debugging of the early
boot process harder especially since there's no easy way to restore the core
dump generation.

This patch introduces a new kernel command line option which specifies an
absolute path where the kernel should write the core dump file when an early
process crashes.

This will take effect until systemd-coredump (or any other handlers) takes
over.
This commit is contained in:
Franck Bui 2018-10-08 16:09:59 +02:00 committed by Zbigniew Jędrzejewski-Szmek
parent d09a71356e
commit c6885f5f36
2 changed files with 44 additions and 3 deletions

View File

@ -55,6 +55,7 @@
<term><varname>systemd.unit=</varname></term>
<term><varname>rd.systemd.unit=</varname></term>
<term><varname>systemd.dump_core</varname></term>
<term><varname>systemd.early_core_pattern=</varname></term>
<term><varname>systemd.crash_chvt</varname></term>
<term><varname>systemd.crash_shell</varname></term>
<term><varname>systemd.crash_reboot</varname></term>
@ -90,6 +91,16 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.early_core_pattern=</varname></term>
<listitem>
<para>During early boot, the generation of core dump files is disabled until a core dump handler (if any)
takes over. This parameter allows to specifies an absolute path where core dump files should be stored until
a handler is installed. The path should be absolute and may contain specifiers, see
<citerefentry><refentrytitle>core</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.restore_state=</varname></term>
<listitem>

View File

@ -109,6 +109,7 @@ static usec_t arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL;
static unsigned arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST;
static usec_t arg_runtime_watchdog = 0;
static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
static char *arg_early_core_pattern = NULL;
static char *arg_watchdog_device = NULL;
static char **arg_default_environment = NULL;
static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
@ -351,6 +352,16 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
else
arg_dump_core = r;
} else if (proc_cmdline_key_streq(key, "systemd.early_core_pattern")) {
if (proc_cmdline_value_missing(key, value))
return 0;
if (path_is_absolute(value))
(void) parse_path_argument_and_warn(value, false, &arg_early_core_pattern);
else
log_warning("Specified core pattern '%s' is not an absolute path, ignoring.", value);
} else if (proc_cmdline_key_streq(key, "systemd.crash_chvt")) {
if (!value)
@ -466,7 +477,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
parse_path_argument_and_warn(value, false, &arg_watchdog_device);
(void) parse_path_argument_and_warn(value, false, &arg_watchdog_device);
} else if (streq(key, "quiet") && !value) {
@ -1482,13 +1493,29 @@ static void initialize_coredump(bool skip_setup) {
if (setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0)
log_warning_errno(errno, "Failed to set RLIMIT_CORE: %m");
/* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored
* until the systemd-coredump tool is enabled via sysctl. */
/* But at the same time, turn off the core_pattern logic by default, so that no
* coredumps are stored until the systemd-coredump tool is enabled via
* sysctl. However it can be changed via the kernel command line later so core
* dumps can still be generated during early startup and in initramfs. */
if (!skip_setup)
disable_coredumps();
#endif
}
static void initialize_core_pattern(bool skip_setup) {
int r;
if (skip_setup || !arg_early_core_pattern)
return;
if (getpid_cached() != 1)
return;
r = write_string_file("/proc/sys/kernel/core_pattern", arg_early_core_pattern, 0);
if (r < 0)
log_warning_errno(r, "Failed to write '%s' to /proc/sys/kernel/core_pattern, ignoring: %m", arg_early_core_pattern);
}
static void do_reexecute(
int argc,
char *argv[],
@ -2345,6 +2372,9 @@ int main(int argc, char *argv[]) {
if (arg_action == ACTION_RUN) {
/* A core pattern might have been specified via the cmdline. */
initialize_core_pattern(skip_setup);
/* Close logging fds, in order not to confuse collecting passed fds and terminal logic below */
log_close();