Skip to content

Commit 91eadfd

Browse files
committed
devices/console: Fix a bug which would cause libkrun to hang on exit
Make PortInputEmpty and PortInputSigInt wait_until_readable implementations poll the stopfd EventFd to ensure the thread eventually exits. If the thread wouldn't exit, the Port::shutdown method would join the thread, and would wait forever for the thread to exit. To replicate the hang, the stdin musn't be a terminal. For example you can use a pipe. `echo "foo" | ./chroot_vm rootfs_fedora /bin/cat` would hang. This is technically a regresion introduced by the commit: 4076b7: devices/console: implement reset method Signed-off-by: Matej Hrica <[email protected]>
1 parent 6be6d15 commit 91eadfd

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

src/devices/src/virtio/console/port_io.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,18 @@ impl PortInput for PortInputSigInt {
222222
fn read_volatile(&mut self, buf: &mut VolatileSlice) -> Result<usize, io::Error> {
223223
self.sigint_evt.read()?;
224224
log::trace!("SIGINT received");
225-
buf.copy_from(&[3u8]); //ASCII 'ETX' -> generates SIGINIT in a terminal
225+
buf.copy_from(&[3u8]); // ASCII 'ETX' -> generates SIGINIT in a terminal
226226
Ok(1)
227227
}
228228

229-
fn wait_until_readable(&self, _stopfd: Option<&EventFd>) {
230-
let mut poll_fds = [PollFd::new(self.sigint_evt.as_raw_fd(), PollFlags::POLLIN)];
229+
fn wait_until_readable(&self, stopfd: Option<&EventFd>) {
230+
let mut poll_fds = Vec::new();
231+
232+
poll_fds.push(PollFd::new(self.sigint_evt.as_raw_fd(), PollFlags::POLLIN));
233+
if let Some(stopfd) = stopfd {
234+
poll_fds.push(PollFd::new(stopfd.as_raw_fd(), PollFlags::POLLIN));
235+
}
236+
231237
poll(&mut poll_fds, -1).expect("Failed to poll");
232238
}
233239
}
@@ -251,7 +257,12 @@ impl PortInput for PortInputEmpty {
251257
Ok(0)
252258
}
253259

254-
fn wait_until_readable(&self, _stopfd: Option<&EventFd>) {
255-
std::thread::sleep(std::time::Duration::MAX);
260+
fn wait_until_readable(&self, stopfd: Option<&EventFd>) {
261+
if let Some(stopfd) = stopfd {
262+
let mut poll_fds = [PollFd::new(stopfd.as_raw_fd(), PollFlags::POLLIN)];
263+
poll(&mut poll_fds, -1).expect("Failed to poll");
264+
} else {
265+
std::thread::sleep(std::time::Duration::MAX);
266+
}
256267
}
257268
}

0 commit comments

Comments
 (0)