virtio-devices: Report errors from EpollHelperHandler::handle_event

Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
Bo Chen 2022-08-11 18:30:13 -07:00 committed by Rob Bradford
parent a7f3620564
commit b1752994d5
13 changed files with 502 additions and 330 deletions

View File

@ -18,6 +18,7 @@ use crate::{
VirtioDeviceType, VirtioInterrupt, VirtioInterruptType, EPOLL_HELPER_EVENT_LAST, VirtioDeviceType, VirtioInterrupt, VirtioInterruptType, EPOLL_HELPER_EVENT_LAST,
VIRTIO_F_VERSION_1, VIRTIO_F_VERSION_1,
}; };
use anyhow::anyhow;
use libc::EFD_NONBLOCK; use libc::EFD_NONBLOCK;
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::io; use std::io;
@ -330,14 +331,18 @@ impl BalloonEpollHandler {
} }
impl EpollHelperHandler for BalloonEpollHandler { impl EpollHelperHandler for BalloonEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
RESIZE_EVENT => { RESIZE_EVENT => {
if let Err(e) = self.resize_receiver.evt.read() { self.resize_receiver.evt.read().map_err(|e| {
error!("Failed to get resize event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get resize event: {:?}", e))
return true; })?;
}
let mut signal_error = false; let mut signal_error = false;
let r = { let r = {
let mut config = self.config.lock().unwrap(); let mut config = self.config.lock().unwrap();
@ -350,57 +355,78 @@ impl EpollHelperHandler for BalloonEpollHandler {
Ok(()) Ok(())
} }
}; };
let ret_err = anyhow!("{:?}", r);
if let Err(e) = &r { if let Err(e) = &r {
// This error will send back to resize caller. // This error will send back to resize caller.
error!("Handle resize event get error: {:?}", e); error!("Handle resize event get error: {:?}", e);
} }
if let Err(e) = self.resize_receiver.send(r) { if let Err(e) = self.resize_receiver.send(r) {
error!("Sending \"resize\" generated error: {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Sending \"resize\" generated error: {:?}",
e
)));
} }
if signal_error { if signal_error {
return true; return Err(EpollHelperError::HandleEvent(ret_err));
} }
} }
INFLATE_QUEUE_EVENT => { INFLATE_QUEUE_EVENT => {
if let Err(e) = self.inflate_queue_evt.read() { self.inflate_queue_evt.read().map_err(|e| {
error!("Failed to get inflate queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to get inflate queue event: {:?}",
} else if let Err(e) = self.process_queue(0) { e
error!("Failed to signal used inflate queue: {:?}", e); ))
return true; })?;
} self.process_queue(0).map_err(|e| {
EpollHelperError::HandleEvent(anyhow!(
"Failed to signal used inflate queue: {:?}",
e
))
})?;
} }
DEFLATE_QUEUE_EVENT => { DEFLATE_QUEUE_EVENT => {
if let Err(e) = self.deflate_queue_evt.read() { self.deflate_queue_evt.read().map_err(|e| {
error!("Failed to get deflate queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to get deflate queue event: {:?}",
} else if let Err(e) = self.process_queue(1) { e
error!("Failed to signal used deflate queue: {:?}", e); ))
return true; })?;
} self.process_queue(1).map_err(|e| {
EpollHelperError::HandleEvent(anyhow!(
"Failed to signal used deflate queue: {:?}",
e
))
})?;
} }
REPORTING_QUEUE_EVENT => { REPORTING_QUEUE_EVENT => {
if let Some(reporting_queue_evt) = self.reporting_queue_evt.as_ref() { if let Some(reporting_queue_evt) = self.reporting_queue_evt.as_ref() {
if let Err(e) = reporting_queue_evt.read() { reporting_queue_evt.read().map_err(|e| {
error!("Failed to get reporting queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to get reporting queue event: {:?}",
} else if let Err(e) = self.process_reporting_queue(2) { e
error!("Failed to signal used inflate queue: {:?}", e); ))
return true; })?;
} self.process_reporting_queue(2).map_err(|e| {
EpollHelperError::HandleEvent(anyhow!(
"Failed to signal used inflate queue: {:?}",
e
))
})?;
} else { } else {
error!("Invalid reporting queue event as no eventfd registered"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Invalid reporting queue event as no eventfd registered"
)));
} }
} }
_ => { _ => {
error!("Unknown event for virtio-balloon"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unknown event for virtio-balloon"
)));
} }
} }
false Ok(())
} }
} }

View File

@ -18,6 +18,7 @@ use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread; use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use anyhow::anyhow;
use block_util::{ use block_util::{
async_io::AsyncIo, async_io::AsyncIoError, async_io::DiskFile, build_disk_image_id, Request, async_io::AsyncIo, async_io::AsyncIoError, async_io::DiskFile, build_disk_image_id, Request,
RequestType, VirtioBlockConfig, RequestType, VirtioBlockConfig,
@ -277,14 +278,17 @@ impl BlockEpollHandler {
} }
impl EpollHelperHandler for BlockEpollHandler { impl EpollHelperHandler for BlockEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
QUEUE_AVAIL_EVENT => { QUEUE_AVAIL_EVENT => {
if let Err(e) = self.queue_evt.read() { self.queue_evt.read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
}
let rate_limit_reached = let rate_limit_reached =
self.rate_limiter.as_ref().map_or(false, |r| r.is_blocked()); self.rate_limiter.as_ref().map_or(false, |r| r.is_blocked());
@ -295,36 +299,43 @@ impl EpollHelperHandler for BlockEpollHandler {
Ok(needs_notification) => { Ok(needs_notification) => {
if needs_notification { if needs_notification {
if let Err(e) = self.signal_used_queue() { if let Err(e) = self.signal_used_queue() {
error!("Failed to signal used queue: {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
e
)));
} }
} }
} }
Err(e) => { Err(e) => {
error!("Failed to process queue (submit): {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to process queue (submit): {:?}",
e
)));
} }
} }
} }
} }
COMPLETION_EVENT => { COMPLETION_EVENT => {
if let Err(e) = self.disk_image.notifier().read() { self.disk_image.notifier().read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
}
match self.process_queue_complete() { match self.process_queue_complete() {
Ok(needs_notification) => { Ok(needs_notification) => {
if needs_notification { if needs_notification {
if let Err(e) = self.signal_used_queue() { if let Err(e) = self.signal_used_queue() {
error!("Failed to signal used queue: {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
e
)));
} }
} }
} }
Err(e) => { Err(e) => {
error!("Failed to process queue (complete): {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to process queue (complete): {:?}",
e
)));
} }
} }
} }
@ -337,28 +348,35 @@ impl EpollHelperHandler for BlockEpollHandler {
Ok(needs_notification) => { Ok(needs_notification) => {
if needs_notification { if needs_notification {
if let Err(e) = self.signal_used_queue() { if let Err(e) = self.signal_used_queue() {
error!("Failed to signal used queue: {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
e
)));
} }
} }
} }
Err(e) => { Err(e) => {
error!("Failed to process queue (submit): {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to process queue (submit): {:?}",
e
)));
} }
} }
} }
} else { } else {
error!("Unexpected 'RATE_LIMITER_EVENT' when rate_limiter is not enabled."); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected 'RATE_LIMITER_EVENT' when rate_limiter is not enabled."
)));
} }
} }
_ => { _ => {
error!("Unexpected event: {}", ev_type); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected event: {}",
ev_type
)));
} }
} }
false Ok(())
} }
} }

View File

@ -11,6 +11,7 @@ use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread; use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use anyhow::anyhow;
use libc::{EFD_NONBLOCK, TIOCGWINSZ}; use libc::{EFD_NONBLOCK, TIOCGWINSZ};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::cmp; use std::cmp;
@ -233,57 +234,76 @@ impl ConsoleEpollHandler {
} }
impl EpollHelperHandler for ConsoleEpollHandler { impl EpollHelperHandler for ConsoleEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
INPUT_QUEUE_EVENT => { INPUT_QUEUE_EVENT => {
if let Err(e) = self.input_queue_evt.read() { self.input_queue_evt.read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.process_input_queue() { if self.process_input_queue() {
if let Err(e) = self.signal_used_queue(0) { self.signal_used_queue(0).map_err(|e| {
error!("Failed to signal used queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
} e
))
})?;
} }
} }
OUTPUT_QUEUE_EVENT => { OUTPUT_QUEUE_EVENT => {
if let Err(e) = self.output_queue_evt.read() { self.output_queue_evt.read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.process_output_queue() { if self.process_output_queue() {
if let Err(e) = self.signal_used_queue(1) { self.signal_used_queue(1).map_err(|e| {
error!("Failed to signal used queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
} e
))
})?;
} }
} }
INPUT_EVENT => { INPUT_EVENT => {
if let Err(e) = self.input_evt.read() { self.input_evt.read().map_err(|e| {
error!("Failed to get input event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get input event: {:?}", e))
return true; })?;
} else if self.process_input_queue() { if self.process_input_queue() {
if let Err(e) = self.signal_used_queue(0) { self.signal_used_queue(0).map_err(|e| {
error!("Failed to signal used queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
} e
))
})?;
} }
} }
CONFIG_EVENT => { CONFIG_EVENT => {
if let Err(e) = self.config_evt.read() { self.config_evt.read().map_err(|e| {
error!("Failed to get config event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get config event: {:?}", e))
return true; })?;
} else if let Err(e) = self.interrupt_cb.trigger(VirtioInterruptType::Config) { self.interrupt_cb
error!("Failed to signal console driver: {:?}", e); .trigger(VirtioInterruptType::Config)
return true; .map_err(|e| {
} EpollHelperError::HandleEvent(anyhow!(
"Failed to signal console driver: {:?}",
e
))
})?;
} }
RESIZE_EVENT => { RESIZE_EVENT => {
if let Err(e) = self.resize_pipe.as_ref().unwrap().read_exact(&mut [0]) { self.resize_pipe
error!("Failed to get resize event: {:?}", e); .as_ref()
return true; .unwrap()
} .read_exact(&mut [0])
.map_err(|e| {
EpollHelperError::HandleEvent(anyhow!(
"Failed to get resize event: {:?}",
e
))
})?;
self.resizer.update_console_size(); self.resizer.update_console_size();
} }
FILE_EVENT => { FILE_EVENT => {
@ -295,19 +315,22 @@ impl EpollHelperHandler for ConsoleEpollHandler {
} }
if self.process_input_queue() { if self.process_input_queue() {
if let Err(e) = self.signal_used_queue(0) { self.signal_used_queue(0).map_err(|e| {
error!("Failed to signal used queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
} e
))
})?;
} }
} }
} }
_ => { _ => {
error!("Unknown event for virtio-console"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unknown event for virtio-console"
)));
} }
} }
false Ok(())
} }
} }

View File

@ -13,6 +13,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::thread; use std::thread;
use thiserror::Error;
use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::eventfd::EventFd;
pub struct EpollHelper { pub struct EpollHelper {
@ -20,13 +21,20 @@ pub struct EpollHelper {
epoll_file: File, epoll_file: File,
} }
#[derive(Debug)] #[derive(Error, Debug)]
pub enum EpollHelperError { pub enum EpollHelperError {
#[error("Failed to create Fd: {0}")]
CreateFd(std::io::Error), CreateFd(std::io::Error),
#[error("Failed to epoll_ctl: {0}")]
Ctl(std::io::Error), Ctl(std::io::Error),
#[error("IO error: {0}")]
IoError(std::io::Error), IoError(std::io::Error),
#[error("Failed to epoll_wait: {0}")]
Wait(std::io::Error), Wait(std::io::Error),
#[error("Failed to get virtio-queue index: {0}")]
QueueRingIndex(virtio_queue::Error), QueueRingIndex(virtio_queue::Error),
#[error("Failed to handle virtio device events: {0}")]
HandleEvent(anyhow::Error),
} }
pub const EPOLL_HELPER_EVENT_PAUSE: u16 = 0; pub const EPOLL_HELPER_EVENT_PAUSE: u16 = 0;
@ -34,8 +42,11 @@ pub const EPOLL_HELPER_EVENT_KILL: u16 = 1;
pub const EPOLL_HELPER_EVENT_LAST: u16 = 15; pub const EPOLL_HELPER_EVENT_LAST: u16 = 15;
pub trait EpollHelperHandler { pub trait EpollHelperHandler {
// Return true if the loop execution should be stopped fn handle_event(
fn handle_event(&mut self, helper: &mut EpollHelper, event: &epoll::Event) -> bool; &mut self,
helper: &mut EpollHelper,
event: &epoll::Event,
) -> Result<(), EpollHelperError>;
} }
impl EpollHelper { impl EpollHelper {
@ -155,9 +166,7 @@ impl EpollHelper {
let _ = self.pause_evt.read(); let _ = self.pause_evt.read();
} }
_ => { _ => {
if handler.handle_event(self, event) { handler.handle_event(self, event)?;
return Ok(());
}
} }
} }
} }

View File

@ -11,6 +11,7 @@ use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread; use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::{DmaRemapping, VirtioInterrupt, VirtioInterruptType}; use crate::{DmaRemapping, VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
@ -725,37 +726,49 @@ impl IommuEpollHandler {
} }
impl EpollHelperHandler for IommuEpollHandler { impl EpollHelperHandler for IommuEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
REQUEST_Q_EVENT => { REQUEST_Q_EVENT => {
if let Err(e) = self.queue_evts[0].read() { self.queue_evts[0].read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.request_queue() {
if let Err(e) = self.signal_used_queue(0) { if self.request_queue() {
error!("Failed to signal used queue: {:?}", e); self.signal_used_queue(0).map_err(|e| {
return true; EpollHelperError::HandleEvent(anyhow!(
} "Failed to signal used queue: {:?}",
e
))
})?;
} }
} }
EVENT_Q_EVENT => { EVENT_Q_EVENT => {
if let Err(e) = self.queue_evts[1].read() { self.queue_evts[1].read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.event_queue() {
if let Err(e) = self.signal_used_queue(1) { if self.event_queue() {
error!("Failed to signal used queue: {:?}", e); self.signal_used_queue(1).map_err(|e| {
return true; EpollHelperError::HandleEvent(anyhow!(
} "Failed to signal used queue: {:?}",
e
))
})?;
} }
} }
_ => { _ => {
error!("Unexpected event: {}", ev_type); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected event: {}",
ev_type
)));
} }
} }
false Ok(())
} }
} }

View File

@ -724,54 +724,65 @@ impl MemEpollHandler {
} }
impl EpollHelperHandler for MemEpollHandler { impl EpollHelperHandler for MemEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
RESIZE_EVENT => { RESIZE_EVENT => {
if let Err(e) = self.resize.evt.read() { self.resize.evt.read().map_err(|e| {
error!("Failed to get resize event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get resize event: {:?}", e))
return true; })?;
} else {
let size = self.resize.size(); let size = self.resize.size();
let mut config = self.config.lock().unwrap(); let mut config = self.config.lock().unwrap();
let mut signal_error = false; let mut signal_error = false;
let mut r = config.resize(size); let mut r = config.resize(size);
r = match r { r = match r {
Err(e) => Err(e), Err(e) => Err(e),
_ => match self.signal(VirtioInterruptType::Config) { _ => match self.signal(VirtioInterruptType::Config) {
Err(e) => { Err(e) => {
signal_error = true; signal_error = true;
Err(Error::ResizeTriggerFail(e)) Err(Error::ResizeTriggerFail(e))
} }
_ => Ok(()), _ => Ok(()),
}, },
}; };
if let Err(e) = self.resize.send(r) { let ret_err = anyhow!("{:?}", r);
error!("Sending \"resize\" response: {:?}", e); if let Err(e) = self.resize.send(r) {
return true; return Err(EpollHelperError::HandleEvent(anyhow!(
} "Sending \"resize\" response: {:?}",
if signal_error { e
return true; )));
} }
if signal_error {
return Err(EpollHelperError::HandleEvent(anyhow!(ret_err)));
} }
} }
QUEUE_AVAIL_EVENT => { QUEUE_AVAIL_EVENT => {
if let Err(e) = self.queue_evt.read() { self.queue_evt.read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.process_queue() {
if let Err(e) = self.signal(VirtioInterruptType::Queue(0)) { if self.process_queue() {
error!("Failed to signal used queue: {:?}", e); self.signal(VirtioInterruptType::Queue(0)).map_err(|e| {
return true; EpollHelperError::HandleEvent(anyhow!(
} "Failed to signal used queue: {:?}",
e
))
})?;
} }
} }
_ => { _ => {
error!("Unexpected event: {}", ev_type); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected event: {}",
ev_type
)));
} }
} }
false Ok(())
} }
} }

View File

@ -15,6 +15,7 @@ use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread; use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::VirtioInterrupt; use crate::VirtioInterrupt;
use anyhow::anyhow;
use net_util::CtrlQueue; use net_util::CtrlQueue;
use net_util::{ use net_util::{
build_net_config_space, build_net_config_space_with_mq, open_tap, build_net_config_space, build_net_config_space_with_mq, open_tap,
@ -84,44 +85,55 @@ impl NetCtrlEpollHandler {
} }
impl EpollHelperHandler for NetCtrlEpollHandler { impl EpollHelperHandler for NetCtrlEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
CTRL_QUEUE_EVENT => { CTRL_QUEUE_EVENT => {
let mem = self.mem.memory(); let mem = self.mem.memory();
if let Err(e) = self.queue_evt.read() { self.queue_evt.read().map_err(|e| {
error!("Failed to get control queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to get control queue event: {:?}",
} e
if let Err(e) = ))
self.ctrl_q })?;
.process(mem.deref(), &mut self.queue, self.access_platform.as_ref()) self.ctrl_q
{ .process(mem.deref(), &mut self.queue, self.access_platform.as_ref())
error!("Failed to process control queue: {:?}", e); .map_err(|e| {
return true; EpollHelperError::HandleEvent(anyhow!(
} else { "Failed to process control queue: {:?}",
match self.queue.needs_notification(mem.deref()) { e
Ok(true) => { ))
if let Err(e) = self.signal_used_queue(self.queue_index) { })?;
error!("Error signalling that control queue was used: {:?}", e); match self.queue.needs_notification(mem.deref()) {
return true; Ok(true) => {
} self.signal_used_queue(self.queue_index).map_err(|e| {
} EpollHelperError::HandleEvent(anyhow!(
Ok(false) => {} "Error signalling that control queue was used: {:?}",
Err(e) => { e
error!("Error getting notification state of control queue: {}", e); ))
return true; })?;
}
} }
} Ok(false) => {}
Err(e) => {
return Err(EpollHelperError::HandleEvent(anyhow!(
"Error getting notification state of control queue: {}",
e
)));
}
};
} }
_ => { _ => {
error!("Unknown event for virtio-net control queue"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unknown event for virtio-net control queue"
)));
} }
} }
false Ok(())
} }
} }
@ -290,15 +302,18 @@ impl NetEpollHandler {
} }
impl EpollHelperHandler for NetEpollHandler { impl EpollHelperHandler for NetEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
RX_QUEUE_EVENT => { RX_QUEUE_EVENT => {
self.driver_awake = true; self.driver_awake = true;
if let Err(e) = self.handle_rx_event() { self.handle_rx_event().map_err(|e| {
error!("Error processing RX queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Error processing RX queue: {:?}", e))
return true; })?;
}
} }
TX_QUEUE_EVENT => { TX_QUEUE_EVENT => {
let queue_evt = &self.queue_evt_pair[1]; let queue_evt = &self.queue_evt_pair[1];
@ -306,22 +321,22 @@ impl EpollHelperHandler for NetEpollHandler {
error!("Failed to get tx queue event: {:?}", e); error!("Failed to get tx queue event: {:?}", e);
} }
self.driver_awake = true; self.driver_awake = true;
if let Err(e) = self.handle_tx_event() { self.handle_tx_event().map_err(|e| {
error!("Error processing TX queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Error processing TX queue: {:?}", e))
return true; })?;
}
} }
TX_TAP_EVENT => { TX_TAP_EVENT => {
if let Err(e) = self.handle_tx_event() { self.handle_tx_event().map_err(|e| {
error!("Error processing TX queue (TAP event): {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Error processing TX queue (TAP event): {:?}",
} e
))
})?;
} }
RX_TAP_EVENT => { RX_TAP_EVENT => {
if let Err(e) = self.handle_rx_tap_event() { self.handle_rx_tap_event().map_err(|e| {
error!("Error processing tap queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Error processing tap queue: {:?}", e))
return true; })?;
}
} }
RX_RATE_LIMITER_EVENT => { RX_RATE_LIMITER_EVENT => {
if let Some(rate_limiter) = &mut self.net.rx_rate_limiter { if let Some(rate_limiter) = &mut self.net.rx_rate_limiter {
@ -336,20 +351,25 @@ impl EpollHelperHandler for NetEpollHandler {
epoll::Events::EPOLLIN, epoll::Events::EPOLLIN,
u64::from(self.net.tap_rx_event_id), u64::from(self.net.tap_rx_event_id),
) { ) {
error!("Error register_listener with `RX_RATE_LIMITER_EVENT`: {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Error register_listener with `RX_RATE_LIMITER_EVENT`: {:?}",
e
)));
} }
self.net.rx_tap_listening = true; self.net.rx_tap_listening = true;
} }
} }
Err(e) => { Err(e) => {
error!("Error from 'rate_limiter.event_handler()': {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Error from 'rate_limiter.event_handler()': {:?}",
e
)));
} }
} }
} else { } else {
error!("Unexpected RX_RATE_LIMITER_EVENT"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected RX_RATE_LIMITER_EVENT"
)));
} }
} }
TX_RATE_LIMITER_EVENT => { TX_RATE_LIMITER_EVENT => {
@ -360,26 +380,33 @@ impl EpollHelperHandler for NetEpollHandler {
Ok(_) => { Ok(_) => {
self.driver_awake = true; self.driver_awake = true;
if let Err(e) = self.process_tx() { if let Err(e) = self.process_tx() {
error!("Error processing TX queue: {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Error processing TX queue: {:?}",
e
)));
} }
} }
Err(e) => { Err(e) => {
error!("Error from 'rate_limiter.event_handler()': {:?}", e); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Error from 'rate_limiter.event_handler()': {:?}",
e
)));
} }
} }
} else { } else {
error!("Unexpected TX_RATE_LIMITER_EVENT"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected TX_RATE_LIMITER_EVENT"
)));
} }
} }
_ => { _ => {
error!("Unknown event: {}", ev_type); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected event: {}",
ev_type
)));
} }
} }
false Ok(())
} }
} }

View File

@ -16,6 +16,7 @@ use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread; use crate::thread_helper::spawn_virtio_thread;
use crate::{GuestMemoryMmap, MmapRegion}; use crate::{GuestMemoryMmap, MmapRegion};
use crate::{VirtioInterrupt, VirtioInterruptType}; use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::fs::File; use std::fs::File;
@ -241,26 +242,35 @@ impl PmemEpollHandler {
} }
impl EpollHelperHandler for PmemEpollHandler { impl EpollHelperHandler for PmemEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
QUEUE_AVAIL_EVENT => { QUEUE_AVAIL_EVENT => {
if let Err(e) = self.queue_evt.read() { self.queue_evt.read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.process_queue() {
if let Err(e) = self.signal_used_queue() { if self.process_queue() {
error!("Failed to signal used queue: {:?}", e); self.signal_used_queue().map_err(|e| {
return true; EpollHelperError::HandleEvent(anyhow!(
} "Failed to signal used queue: {:?}",
e
))
})?;
} }
} }
_ => { _ => {
error!("Unexpected event: {}", ev_type); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected event: {}",
ev_type
)));
} }
} }
false Ok(())
} }
} }

View File

@ -12,6 +12,7 @@ use crate::seccomp_filters::Thread;
use crate::thread_helper::spawn_virtio_thread; use crate::thread_helper::spawn_virtio_thread;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use crate::{VirtioInterrupt, VirtioInterruptType}; use crate::{VirtioInterrupt, VirtioInterruptType};
use anyhow::anyhow;
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
@ -103,26 +104,34 @@ impl RngEpollHandler {
} }
impl EpollHelperHandler for RngEpollHandler { impl EpollHelperHandler for RngEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
QUEUE_AVAIL_EVENT => { QUEUE_AVAIL_EVENT => {
if let Err(e) = self.queue_evt.read() { self.queue_evt.read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.process_queue() { if self.process_queue() {
if let Err(e) = self.signal_used_queue() { self.signal_used_queue().map_err(|e| {
error!("Failed to signal used queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to signal used queue: {:?}",
} e
))
})?;
} }
} }
_ => { _ => {
error!("Unexpected event: {}", ev_type); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected event: {}",
ev_type
)));
} }
} }
false Ok(())
} }
} }

View File

@ -256,30 +256,39 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
} }
impl<S: VhostUserMasterReqHandler> EpollHelperHandler for VhostUserEpollHandler<S> { impl<S: VhostUserMasterReqHandler> EpollHelperHandler for VhostUserEpollHandler<S> {
fn handle_event(&mut self, helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
helper: &mut EpollHelper,
event: &epoll::Event,
) -> std::result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
HUP_CONNECTION_EVENT => { HUP_CONNECTION_EVENT => {
if let Err(e) = self.reconnect(helper) { self.reconnect(helper).map_err(|e| {
error!("failed to reconnect vhost-user backend: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "failed to reconnect vhost-user backend: {:?}",
} e
))
})?;
} }
SLAVE_REQ_EVENT => { SLAVE_REQ_EVENT => {
if let Some(slave_req_handler) = self.slave_req_handler.as_mut() { if let Some(slave_req_handler) = self.slave_req_handler.as_mut() {
if let Err(e) = slave_req_handler.handle_request() { slave_req_handler.handle_request().map_err(|e| {
error!("Failed to handle request from vhost-user backend: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to handle request from vhost-user backend: {:?}",
} e
))
})?;
} }
} }
_ => { _ => {
error!("Unknown event for vhost-user thread"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unknown event for vhost-user thread"
)));
} }
} }
false Ok(())
} }
} }

View File

@ -37,6 +37,7 @@ use crate::{
EpollHelperHandler, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType, EpollHelperHandler, VirtioCommon, VirtioDevice, VirtioDeviceType, VirtioInterruptType,
EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IN_ORDER, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1, EPOLL_HELPER_EVENT_LAST, VIRTIO_F_IN_ORDER, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1,
}; };
use anyhow::anyhow;
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use seccompiler::SeccompAction; use seccompiler::SeccompAction;
use std::io; use std::io;
@ -222,13 +223,17 @@ impl<B> EpollHelperHandler for VsockEpollHandler<B>
where where
B: VsockBackend, B: VsockBackend,
{ {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let evset = match epoll::Events::from_bits(event.events) { let evset = match epoll::Events::from_bits(event.events) {
Some(evset) => evset, Some(evset) => evset,
None => { None => {
let evbits = event.events; let evbits = event.events;
warn!("epoll: ignoring unknown event set: 0x{:x}", evbits); warn!("epoll: ignoring unknown event set: 0x{:x}", evbits);
return false; return Ok(());
} }
}; };
@ -236,43 +241,45 @@ where
match ev_type { match ev_type {
RX_QUEUE_EVENT => { RX_QUEUE_EVENT => {
debug!("vsock: RX queue event"); debug!("vsock: RX queue event");
if let Err(e) = self.queue_evts[0].read() { self.queue_evts[0].read().map_err(|e| {
error!("Failed to get RX queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get RX queue event: {:?}", e))
return true; })?;
} else if self.backend.read().unwrap().has_pending_rx() { if self.backend.read().unwrap().has_pending_rx() {
if let Err(e) = self.process_rx() { self.process_rx().map_err(|e| {
error!("Failed to process RX queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to process RX queue: {:?}",
} e
))
})?;
} }
} }
TX_QUEUE_EVENT => { TX_QUEUE_EVENT => {
debug!("vsock: TX queue event"); debug!("vsock: TX queue event");
if let Err(e) = self.queue_evts[1].read() { self.queue_evts[1].read().map_err(|e| {
error!("Failed to get TX queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get TX queue event: {:?}", e))
return true; })?;
} else {
if let Err(e) = self.process_tx() { self.process_tx().map_err(|e| {
error!("Failed to process TX queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to process TX queue: {:?}", e))
return true; })?;
}
// The backend may have queued up responses to the packets we sent during TX queue // The backend may have queued up responses to the packets we sent during TX queue
// processing. If that happened, we need to fetch those responses and place them // processing. If that happened, we need to fetch those responses and place them
// into RX buffers. // into RX buffers.
if self.backend.read().unwrap().has_pending_rx() { if self.backend.read().unwrap().has_pending_rx() {
if let Err(e) = self.process_rx() { self.process_rx().map_err(|e| {
error!("Failed to process RX queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to process RX queue: {:?}",
} e
} ))
})?;
} }
} }
EVT_QUEUE_EVENT => { EVT_QUEUE_EVENT => {
debug!("vsock: EVT queue event"); debug!("vsock: EVT queue event");
if let Err(e) = self.queue_evts[2].read() { self.queue_evts[2].read().map_err(|e| {
error!("Failed to get EVT queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get EVT queue event: {:?}", e))
return true; })?;
}
} }
BACKEND_EVENT => { BACKEND_EVENT => {
debug!("vsock: backend event"); debug!("vsock: backend event");
@ -282,24 +289,26 @@ where
// In particular, if `self.backend.send_pkt()` halted the TX queue processing (by // In particular, if `self.backend.send_pkt()` halted the TX queue processing (by
// returning an error) at some point in the past, now is the time to try walking the // returning an error) at some point in the past, now is the time to try walking the
// TX queue again. // TX queue again.
if let Err(e) = self.process_tx() { self.process_tx().map_err(|e| {
error!("Failed to process TX queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to process TX queue: {:?}", e))
return true; })?;
}
if self.backend.read().unwrap().has_pending_rx() { if self.backend.read().unwrap().has_pending_rx() {
if let Err(e) = self.process_rx() { self.process_rx().map_err(|e| {
error!("Failed to process RX queue: {:?}", e); EpollHelperError::HandleEvent(anyhow!(
return true; "Failed to process RX queue: {:?}",
} e
))
})?;
} }
} }
_ => { _ => {
error!("Unknown event for virtio-vsock"); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unknown event for virtio-vsock"
)));
} }
} }
false Ok(())
} }
} }
@ -714,7 +723,7 @@ mod tests {
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap(); EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
assert!( assert!(
ctx.handler.handle_event(&mut epoll_helper, &event), ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
"handle_event() should have failed" "handle_event() should have failed"
); );
} }
@ -783,7 +792,7 @@ mod tests {
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap(); EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
assert!( assert!(
ctx.handler.handle_event(&mut epoll_helper, &event), ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
"handle_event() should have failed" "handle_event() should have failed"
); );
} }
@ -803,7 +812,7 @@ mod tests {
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap(); EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
assert!( assert!(
ctx.handler.handle_event(&mut epoll_helper, &event), ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
"handle_event() should have failed" "handle_event() should have failed"
); );
} }
@ -824,7 +833,7 @@ mod tests {
let event = epoll::Event::new(events, BACKEND_EVENT as u64); let event = epoll::Event::new(events, BACKEND_EVENT as u64);
let mut epoll_helper = let mut epoll_helper =
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap(); EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
ctx.handler.handle_event(&mut epoll_helper, &event); assert!(ctx.handler.handle_event(&mut epoll_helper, &event).is_ok());
// The backend should've received this event. // The backend should've received this event.
assert_eq!( assert_eq!(
@ -850,7 +859,7 @@ mod tests {
let event = epoll::Event::new(events, BACKEND_EVENT as u64); let event = epoll::Event::new(events, BACKEND_EVENT as u64);
let mut epoll_helper = let mut epoll_helper =
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap(); EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
ctx.handler.handle_event(&mut epoll_helper, &event); assert!(ctx.handler.handle_event(&mut epoll_helper, &event).is_ok());
// The backend should've received this event. // The backend should've received this event.
assert_eq!( assert_eq!(
@ -875,7 +884,7 @@ mod tests {
EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap(); EpollHelper::new(&ctx.handler.kill_evt, &ctx.handler.pause_evt).unwrap();
assert!( assert!(
ctx.handler.handle_event(&mut epoll_helper, &event), ctx.handler.handle_event(&mut epoll_helper, &event).is_err(),
"handle_event() should have failed" "handle_event() should have failed"
); );
} }

View File

@ -353,7 +353,7 @@ mod tests {
let event = epoll::Event::new(events, TX_QUEUE_EVENT as u64); let event = epoll::Event::new(events, TX_QUEUE_EVENT as u64);
let mut epoll_helper = let mut epoll_helper =
EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap(); EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap();
self.handler.handle_event(&mut epoll_helper, &event); self.handler.handle_event(&mut epoll_helper, &event).ok();
} }
pub fn signal_rxq_event(&mut self) { pub fn signal_rxq_event(&mut self) {
self.handler.queue_evts[0].write(1).unwrap(); self.handler.queue_evts[0].write(1).unwrap();
@ -361,7 +361,7 @@ mod tests {
let event = epoll::Event::new(events, RX_QUEUE_EVENT as u64); let event = epoll::Event::new(events, RX_QUEUE_EVENT as u64);
let mut epoll_helper = let mut epoll_helper =
EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap(); EpollHelper::new(&self.handler.kill_evt, &self.handler.pause_evt).unwrap();
self.handler.handle_event(&mut epoll_helper, &event); self.handler.handle_event(&mut epoll_helper, &event).ok();
} }
} }
} }

View File

@ -121,28 +121,35 @@ impl WatchdogEpollHandler {
} }
impl EpollHelperHandler for WatchdogEpollHandler { impl EpollHelperHandler for WatchdogEpollHandler {
fn handle_event(&mut self, _helper: &mut EpollHelper, event: &epoll::Event) -> bool { fn handle_event(
&mut self,
_helper: &mut EpollHelper,
event: &epoll::Event,
) -> result::Result<(), EpollHelperError> {
let ev_type = event.data as u16; let ev_type = event.data as u16;
match ev_type { match ev_type {
QUEUE_AVAIL_EVENT => { QUEUE_AVAIL_EVENT => {
if let Err(e) = self.queue_evt.read() { self.queue_evt.read().map_err(|e| {
error!("Failed to get queue event: {:?}", e); EpollHelperError::HandleEvent(anyhow!("Failed to get queue event: {:?}", e))
return true; })?;
} else if self.process_queue() {
if let Err(e) = self.signal_used_queue() { if self.process_queue() {
error!("Failed to signal used queue: {:?}", e); self.signal_used_queue().map_err(|e| {
return true; EpollHelperError::HandleEvent(anyhow!(
} "Failed to signal used queue: {:?}",
e
))
})?;
} }
} }
TIMER_EXPIRED_EVENT => { TIMER_EXPIRED_EVENT => {
// When reading from the timerfd you get 8 bytes indicating // When reading from the timerfd you get 8 bytes indicating
// the number of times this event has elapsed since the last read. // the number of times this event has elapsed since the last read.
let mut buf = vec![0; 8]; let mut buf = vec![0; 8];
if let Err(e) = self.timer.read_exact(&mut buf) { self.timer.read_exact(&mut buf).map_err(|e| {
error!("Error reading from timer fd: {:}", e); EpollHelperError::HandleEvent(anyhow!("Error reading from timer fd: {:}", e))
return true; })?;
}
if let Some(last_ping_time) = self.last_ping_time.lock().unwrap().as_ref() { if let Some(last_ping_time) = self.last_ping_time.lock().unwrap().as_ref() {
let now = Instant::now(); let now = Instant::now();
let gap = now.duration_since(*last_ping_time).as_secs(); let gap = now.duration_since(*last_ping_time).as_secs();
@ -151,14 +158,15 @@ impl EpollHelperHandler for WatchdogEpollHandler {
self.reset_evt.write(1).ok(); self.reset_evt.write(1).ok();
} }
} }
return false;
} }
_ => { _ => {
error!("Unexpected event: {}", ev_type); return Err(EpollHelperError::HandleEvent(anyhow!(
return true; "Unexpected event: {}",
ev_type
)));
} }
} }
false Ok(())
} }
} }