diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml index 0545f9d84b..43b3a3667e 100644 --- a/man/kernel-command-line.xml +++ b/man/kernel-command-line.xml @@ -55,6 +55,7 @@ systemd.unit= rd.systemd.unit= systemd.dump_core + systemd.early_core_pattern= systemd.crash_chvt systemd.crash_shell systemd.crash_reboot @@ -90,6 +91,16 @@ + + systemd.early_core_pattern= + + 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 + core5 for details. + + + systemd.restore_state= diff --git a/src/core/main.c b/src/core/main.c index 078decb432..ce45f2ded2 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -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();