mirror of
https://github.com/systemd/systemd.git
synced 2025-01-27 18:04:05 +03:00
nspawn: make sure our container PID 1 keeps logging to the original stderr as long as possible
If we log to the pty that is configured as stdin/stdout/stderr of the container too early we risk filling it up in full before we start processing the pty from the parent process, resulting in deadlocks. Let's hence keep a copy of the original tty we were started on before setting up stdin/stdout/stderr, so that we can log to it, and keep using it as long as we can. Since the kernel's pty internal buffer is pretty small this actually triggered deadlocks when we debug logged at lot from nspawn's child processes, see: https://github.com/systemd/systemd/pull/9024#issuecomment-390403674 With this change we won't use the pty at all, only the actual payload we start will, and hence we won't deadlock on it, ever.
This commit is contained in:
parent
8ca082b49a
commit
17cac366ae
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -2720,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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user