diff --git a/src/basic/log.c b/src/basic/log.c index 6f442420110..5db65f276f7 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -1330,3 +1330,20 @@ int log_emergency_level(void) { return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR; } + +int log_dup_console(void) { + int copy; + + /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful + * whenever we want to continue logging through the original fd, but want to rearrange stderr. */ + + if (console_fd >= 3) + return 0; + + copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) + return -errno; + + console_fd = copy; + return 0; +} diff --git a/src/basic/log.h b/src/basic/log.h index 63cfd298ec1..6a8cf6375f1 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -284,6 +284,8 @@ void log_set_open_when_needed(bool b); * stderr, the console or kmsg */ void log_set_prohibit_ipc(bool b); +int log_dup_console(void); + int log_syntax_internal( const char *unit, int level, diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a8b4c8224ca..638935d5518 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2597,15 +2597,12 @@ static int inner_child( return r; } - /* Now, explicitly close the log, so that we - * then can close all remaining fds. Closing - * the log explicitly first has the benefit - * that the logging subsystem knows about it, - * and is thus ready to be reopened should we - * need it again. Note that the other fds - * closed here are at least the locking and - * barrier fds. */ + /* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first + * has the benefit that the logging subsystem knows about it, and is thus ready to be reopened should we need + * it again. Note that the other fds closed here are at least the locking and barrier fds. */ log_close(); + log_set_open_when_needed(true); + (void) fdset_close_others(fds); if (arg_start_mode == START_BOOT) { @@ -2643,9 +2640,7 @@ static int inner_child( exec_target = "/bin/bash, /bin/sh"; } - r = -errno; - (void) log_open(); - return log_error_errno(r, "execv(%s) failed: %m", exec_target); + return log_error_errno(errno, "execv(%s) failed: %m", exec_target); } static int setup_sd_notify_child(void) { @@ -2725,6 +2720,11 @@ static int outer_child( if (terminal < 0) return log_error_errno(terminal, "Failed to open console: %m"); + /* Make sure we can continue logging to the original stderr, even if stderr points elsewhere now */ + r = log_dup_console(); + if (r < 0) + return log_error_errno(r, "Failed to duplicate stderr: %m"); + r = rearrange_stdio(terminal, terminal, terminal); /* invalidates 'terminal' on success and failure */ if (r < 0) return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");