mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-11-04 19:11:11 +00:00
vmm: Handle epoll events for PTYs separately
Use two separate events for the console and serial PTY and then drive the handling of the inputs on the PTY separately. This results in the correct behaviour when both console and serial are attached to the PTY as they are triggered separately on the epoll so events are not lost. Fixes: #3012 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
6233f6f68e
commit
4d2a4e2805
@ -148,7 +148,8 @@ pub enum EpollDispatch {
|
||||
Stdin,
|
||||
Api,
|
||||
ActivateVirtioDevices,
|
||||
Pty,
|
||||
ConsolePty,
|
||||
SerialPty,
|
||||
}
|
||||
|
||||
pub struct EpollContext {
|
||||
@ -392,12 +393,12 @@ impl Vmm {
|
||||
)?;
|
||||
if let Some(serial_pty) = vm.serial_pty() {
|
||||
self.epoll
|
||||
.add_event(&serial_pty.main, EpollDispatch::Pty)
|
||||
.add_event(&serial_pty.main, EpollDispatch::SerialPty)
|
||||
.map_err(VmError::EventfdError)?;
|
||||
};
|
||||
if let Some(console_pty) = vm.console_pty() {
|
||||
self.epoll
|
||||
.add_event(&console_pty.main, EpollDispatch::Pty)
|
||||
.add_event(&console_pty.main, EpollDispatch::ConsolePty)
|
||||
.map_err(VmError::EventfdError)?;
|
||||
};
|
||||
self.vm = Some(vm);
|
||||
@ -1295,9 +1296,9 @@ impl Vmm {
|
||||
.map_err(Error::ActivateVirtioDevices)?;
|
||||
}
|
||||
}
|
||||
EpollDispatch::Pty => {
|
||||
event @ (EpollDispatch::ConsolePty | EpollDispatch::SerialPty) => {
|
||||
if let Some(ref vm) = self.vm {
|
||||
vm.handle_pty().map_err(Error::Pty)?;
|
||||
vm.handle_pty(event).map_err(Error::Pty)?;
|
||||
}
|
||||
}
|
||||
EpollDispatch::Api => {
|
||||
|
@ -17,7 +17,6 @@ use crate::config::{
|
||||
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, HotplugMethod, NetConfig, PmemConfig,
|
||||
UserDeviceConfig, ValidationError, VmConfig, VsockConfig,
|
||||
};
|
||||
use crate::cpu;
|
||||
use crate::device_manager::{
|
||||
self, get_win_size, Console, DeviceManager, DeviceManagerError, PtyPair,
|
||||
};
|
||||
@ -26,6 +25,7 @@ use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
||||
use crate::migration::{get_vm_snapshot, url_to_path, VM_SNAPSHOT_FILE};
|
||||
use crate::seccomp_filters::{get_seccomp_filter, Thread};
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::{cpu, EpollDispatch};
|
||||
use crate::{
|
||||
PciDeviceInfo, CPU_MANAGER_SNAPSHOT_ID, DEVICE_MANAGER_SNAPSHOT_ID, MEMORY_MANAGER_SNAPSHOT_ID,
|
||||
};
|
||||
@ -1911,28 +1911,32 @@ impl Vm {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_pty(&self) -> Result<()> {
|
||||
pub fn handle_pty(&self, event: EpollDispatch) -> Result<()> {
|
||||
// Could be a little dangerous, picks up a lock on device_manager
|
||||
// and goes into a blocking read. If the epoll loops starts to be
|
||||
// services by multiple threads likely need to revist this.
|
||||
let dm = self.device_manager.lock().unwrap();
|
||||
let mut out = [0u8; 64];
|
||||
if let Some(mut pty) = dm.serial_pty() {
|
||||
let count = pty.main.read(&mut out).map_err(Error::PtyConsole)?;
|
||||
let console = dm.console();
|
||||
if console.input_enabled() {
|
||||
console
|
||||
.queue_input_bytes_serial(&out[..count])
|
||||
.map_err(Error::Console)?;
|
||||
}
|
||||
};
|
||||
let count = match dm.console_pty() {
|
||||
Some(mut pty) => pty.main.read(&mut out).map_err(Error::PtyConsole)?,
|
||||
None => return Ok(()),
|
||||
};
|
||||
let console = dm.console();
|
||||
if console.input_enabled() {
|
||||
console.queue_input_bytes_console(&out[..count])
|
||||
|
||||
if matches!(event, EpollDispatch::SerialPty) {
|
||||
if let Some(mut pty) = dm.serial_pty() {
|
||||
let mut out = [0u8; 64];
|
||||
let count = pty.main.read(&mut out).map_err(Error::PtyConsole)?;
|
||||
let console = dm.console();
|
||||
if console.input_enabled() {
|
||||
console
|
||||
.queue_input_bytes_serial(&out[..count])
|
||||
.map_err(Error::Console)?;
|
||||
}
|
||||
};
|
||||
} else if matches!(event, EpollDispatch::ConsolePty) {
|
||||
if let Some(mut pty) = dm.console_pty() {
|
||||
let mut out = [0u8; 64];
|
||||
let count = pty.main.read(&mut out).map_err(Error::PtyConsole)?;
|
||||
let console = dm.console();
|
||||
if console.input_enabled() {
|
||||
console.queue_input_bytes_console(&out[..count])
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
Loading…
Reference in New Issue
Block a user