From 09f365899924a168e173f57f67882f5794f1316b Mon Sep 17 00:00:00 2001 From: Chris Webb Date: Mon, 19 Feb 2024 16:27:12 +0000 Subject: [PATCH] vmm: Avoid zombie sigwinch_listener processes When a guest running on a terminal reboots, the sigwinch_listener subprocess exits and a new one restarts. The parent never wait()s for children, so the old subprocess remains as a zombie. With further reboots, more and more zombies build up. As there are no other children for which we want the exit status, the easiest fix is to take advantage of the implicit reaping specified by POSIX when we set the disposition of SIGCHLD to SIG_IGN. For this to work, we also need to set the correct default exit signal of SIGCHLD when using clone3() CLONE_CLEAR_SIGHAND. Unlike the fallback fork() path, clone_args::default() initialises the exit signal to zero, which results in a child with non-standard reaping behaviour. Signed-off-by: Chris Webb --- src/main.rs | 5 +++++ vmm/src/sigwinch_listener.rs | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 86d805620..8e12a55ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -561,6 +561,11 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result, Error> { .ok(); } + // SAFETY: Trivially safe. + unsafe { + libc::signal(libc::SIGCHLD, libc::SIG_IGN); + } + // Before we start any threads, mask the signals we'll be // installing handlers for, to make sure they only ever run on the // dedicated signal handling thread we'll start in a bit. diff --git a/vmm/src/sigwinch_listener.rs b/vmm/src/sigwinch_listener.rs index 0aad87853..716bf2c61 100644 --- a/vmm/src/sigwinch_listener.rs +++ b/vmm/src/sigwinch_listener.rs @@ -6,7 +6,7 @@ use arch::_NSIG; use libc::{ c_int, c_void, close, fork, getpgrp, ioctl, pipe2, poll, pollfd, setsid, sigemptyset, siginfo_t, signal, sigprocmask, syscall, tcgetpgrp, tcsetpgrp, SYS_close_range, EINVAL, ENOSYS, - ENOTTY, O_CLOEXEC, POLLERR, SIGWINCH, SIG_DFL, SIG_SETMASK, STDERR_FILENO, TIOCSCTTY, + ENOTTY, O_CLOEXEC, POLLERR, SIGCHLD, SIGWINCH, SIG_DFL, SIG_SETMASK, STDERR_FILENO, TIOCSCTTY, }; use seccompiler::{apply_filter, BpfProgram}; use std::cell::RefCell; @@ -204,7 +204,10 @@ fn sigwinch_listener_main(seccomp_filter: BpfProgram, tx: File, tty: File) -> ! /// /// Same as [`fork`]. unsafe fn clone_clear_sighand() -> io::Result { - let mut args = clone_args::default(); + let mut args = clone_args { + exit_signal: SIGCHLD as u64, + ..Default::default() + }; args.flags |= CLONE_CLEAR_SIGHAND; let r = clone3(&mut args, size_of::()); if r != -1 {