From 1a484a82f9576126e67534155918e3b63d1e59bd Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 1 Aug 2019 13:00:14 -0700 Subject: [PATCH] vmm: Don't break from epoll loop on EINTR The existing code taking care of the epoll loop was too restrictive as it was propagating the error returned from the epoll_wait() syscall, no matter what was the error. This causes the epoll loop to be broken, leading to the VM termination. This patch enforces the parsing of the returned error and prevent from the error propagation in case it is EINTR, which stands for Interrupted. In case the epoll loop is interrupted, it is appropriate to retry. Signed-off-by: Sebastien Boeuf --- vmm/src/vm.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index a866de0f2..cd09bbdce 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -1454,8 +1454,22 @@ impl<'a> Vm<'a> { } 'outer: loop { - let num_events = - epoll::wait(epoll_fd, -1, &mut events[..]).map_err(Error::EpollError)?; + let num_events = match epoll::wait(epoll_fd, -1, &mut events[..]) { + Ok(res) => res, + Err(e) => { + if e.kind() == io::ErrorKind::Interrupted { + // It's well defined from the epoll_wait() syscall + // documentation that the epoll loop can be interrupted + // before any of the requested events occurred or the + // timeout expired. In both those cases, epoll_wait() + // returns an error of type EINTR, but this should not + // be considered as a regular error. Instead it is more + // appropriate to retry, by calling into epoll_wait(). + continue; + } + return Err(Error::EpollError(e)); + } + }; for event in events.iter().take(num_events) { let dispatch_idx = event.data as usize;