vmm: serial: Wait for PTY to be available before writing to it

The goal of this patch is to provide a reliable way to detect when the
other end of the PTY is connected, and therefore be able to identify
when we can write to the PTY device. This is needed because writing to
the PTY device when the other end isn't connected causes the loss of
the written bytes.

The way to detect the connection on the other end of the PTY is by
knowing the other end is disconnected at first with the presence of the
EPOLLHUP event. Later on, when the connection happens, EPOLLHUP is not
triggered anymore, and that's when we can assume it's okay to write to
the PTY main device.

It's important to note we had to ensure the file descriptor for the
other end was closed, otherwise we would have never seen the EPOLLHUP
event. And we did so by removing the "sub" field from the PtyPair
structure as it was keeping the associated File opened.

Fixes #3170

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2022-08-18 18:22:33 +02:00
committed by Rob Bradford
parent 1ee41a98de
commit cdcd4d259e
3 changed files with 131 additions and 156 deletions

View File

@@ -777,7 +777,6 @@ struct DeviceManagerState {
#[derive(Debug)]
pub struct PtyPair {
pub main: File,
pub sub: File,
pub path: PathBuf,
}
@@ -785,7 +784,6 @@ impl Clone for PtyPair {
fn clone(&self) -> Self {
PtyPair {
main: self.main.try_clone().unwrap(),
sub: self.sub.try_clone().unwrap(),
path: self.path.clone(),
}
}
@@ -1915,7 +1913,7 @@ impl DeviceManager {
let file = main.try_clone().unwrap();
assert!(resize_pipe.is_none());
self.listen_for_sigwinch_on_tty(&sub).unwrap();
self.console_pty = Some(Arc::new(Mutex::new(PtyPair { main, sub, path })));
self.console_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
Endpoint::FilePair(file.try_clone().unwrap(), file)
}
}
@@ -2016,7 +2014,7 @@ impl DeviceManager {
self.set_raw_mode(&mut sub)
.map_err(DeviceManagerError::SetPtyRaw)?;
self.config.lock().unwrap().serial.file = Some(path.clone());
self.serial_pty = Some(Arc::new(Mutex::new(PtyPair { main, sub, path })));
self.serial_pty = Some(Arc::new(Mutex::new(PtyPair { main, path })));
}
None
}