mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
event_monitor: refactor the implementation to support concurrent access
This patch modifies `event_monitor` to ensure that concurrent access to `event_log` from multiple threads is safe. Previously, the `event_log` function would acquire a reference to the event log file and write to it without doing any synchronization, which made it prone to data races. This issue likely went under the radar because the relevant `SAFETY` comment on the unsafe block was incomplete. The new implementation spawns a dedicated thread named `event-monitor` solely for writing to the file. It uses the MPMC channel exposed by `flume` to pass messages to the `event-monitor` thread. Since `flume::Sender<T>` implements `Sync`, it is safe for multiple threads to share it and send messages to the `event-monitor` thread. This is not possible with `std::sync::mpsc::Sender<T>` since it's `!Sync`, meaning it is not safe for it to be shared between different threads. The `event_monitor::set_monitor` function now only initializes the required global state and returns an instance of the `Monitor` struct. This decouples the actual logging logic from the `event_monitor` crate. The `event-monitor` thread is then spawned by the `vmm` crate. Signed-off-by: Omer Faruk Bayram <omer.faruk@sartura.hr>
This commit is contained in:
committed by
Rob Bradford
parent
3d82867fe2
commit
02e1c54426
@@ -126,6 +126,10 @@ pub enum Error {
|
||||
#[error("Error starting D-Bus session: {0}")]
|
||||
CreateDBusSession(#[source] zbus::Error),
|
||||
|
||||
/// Cannot create `event-monitor` thread
|
||||
#[error("Error spawning `event-monitor` thread: {0}")]
|
||||
EventMonitorThreadSpawn(#[source] io::Error),
|
||||
|
||||
/// Cannot handle the VM STDIN stream
|
||||
#[error("Error handling VM stdin: {0:?}")]
|
||||
Stdin(VmError),
|
||||
@@ -289,6 +293,28 @@ impl Serialize for PciDeviceInfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_event_monitor_thread(
|
||||
mut monitor: event_monitor::Monitor,
|
||||
exit_event: EventFd,
|
||||
) -> Result<()> {
|
||||
thread::Builder::new()
|
||||
.name("event-monitor".to_owned())
|
||||
.spawn(move || {
|
||||
std::panic::catch_unwind(AssertUnwindSafe(move || {
|
||||
while let Ok(event) = monitor.rx.recv() {
|
||||
monitor.file.write_all(event.as_bytes().as_ref()).ok();
|
||||
monitor.file.write_all(b"\n\n").ok();
|
||||
}
|
||||
}))
|
||||
.map_err(|_| {
|
||||
error!("`event-monitor` thread panicked");
|
||||
exit_event.write(1).ok();
|
||||
})
|
||||
})
|
||||
.map(|_| ())
|
||||
.map_err(Error::EventMonitorThreadSpawn)
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn start_vmm_thread(
|
||||
|
||||
Reference in New Issue
Block a user