Skip to content

Commit

Permalink
devices/console: Fix a bug which would cause libkrun to hang on exit
Browse files Browse the repository at this point in the history
Make PortInputEmpty and PortInputSigInt `wait_until_readable` implementations
poll the stopfd EventFd to ensure the thread eventually exits.
(The thread is joined in Port::shutdown method causing the hang).

To replicate the hang, the stdin must not be a terminal. For example you can use
a pipe - `echo hello | ./chroot_vm rootfs_fedora /bin/cat` would hang without
this fix.

This seems to be a regresion introduced by the commit:
4076b7: devices/console: implement reset method

Signed-off-by: Matej Hrica <mhrica@redhat.com>
  • Loading branch information
mtjhrc committed Jan 28, 2025
1 parent e9dfe77 commit 6ad1bd0
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions src/devices/src/virtio/console/port_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,13 @@ impl PortInput for PortInputSigInt {
Ok(1)
}

fn wait_until_readable(&self, _stopfd: Option<&EventFd>) {
let mut poll_fds = [PollFd::new(self.sigint_evt.as_raw_fd(), PollFlags::POLLIN)];
fn wait_until_readable(&self, stopfd: Option<&EventFd>) {
let mut poll_fds = Vec::new();
poll_fds.push(PollFd::new(self.sigint_evt.as_raw_fd(), PollFlags::POLLIN));
if let Some(stopfd) = stopfd {
poll_fds.push(PollFd::new(stopfd.as_raw_fd(), PollFlags::POLLIN));
}

poll(&mut poll_fds, -1).expect("Failed to poll");
}
}
Expand All @@ -251,7 +256,12 @@ impl PortInput for PortInputEmpty {
Ok(0)
}

fn wait_until_readable(&self, _stopfd: Option<&EventFd>) {
std::thread::sleep(std::time::Duration::MAX);
fn wait_until_readable(&self, stopfd: Option<&EventFd>) {
if let Some(stopfd) = stopfd {
let mut poll_fds = [PollFd::new(stopfd.as_raw_fd(), PollFlags::POLLIN)];
poll(&mut poll_fds, -1).expect("Failed to poll");
} else {
std::thread::sleep(std::time::Duration::MAX);
}
}
}

0 comments on commit 6ad1bd0

Please sign in to comment.