(
&mut self,
api_receiver: &Receiver<ApiRequest>,
#[cfg(feature = "guest_debug")] gdb_receiver: &Receiver<gdb::GdbRequest>,
)
| 1671 | } |
| 1672 | |
| 1673 | fn control_loop( |
| 1674 | &mut self, |
| 1675 | api_receiver: &Receiver<ApiRequest>, |
| 1676 | #[cfg(feature = "guest_debug")] gdb_receiver: &Receiver<gdb::GdbRequest>, |
| 1677 | ) -> Result<()> { |
| 1678 | const EPOLL_EVENTS_LEN: usize = 100; |
| 1679 | |
| 1680 | let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN]; |
| 1681 | let epoll_fd = self.epoll.as_raw_fd(); |
| 1682 | |
| 1683 | 'outer: loop { |
| 1684 | let num_events = match epoll::wait(epoll_fd, -1, &mut events[..]) { |
| 1685 | Ok(res) => res, |
| 1686 | Err(e) => { |
| 1687 | if e.kind() == io::ErrorKind::Interrupted { |
| 1688 | // It's well defined from the epoll_wait() syscall |
| 1689 | // documentation that the epoll loop can be interrupted |
| 1690 | // before any of the requested events occurred or the |
| 1691 | // timeout expired. In both those cases, epoll_wait() |
| 1692 | // returns an error of type EINTR, but this should not |
| 1693 | // be considered as a regular error. Instead it is more |
| 1694 | // appropriate to retry, by calling into epoll_wait(). |
| 1695 | continue; |
| 1696 | } |
| 1697 | return Err(Error::Epoll(e)); |
| 1698 | } |
| 1699 | }; |
| 1700 | |
| 1701 | for event in events.iter().take(num_events) { |
| 1702 | let dispatch_event: EpollDispatch = event.data.into(); |
| 1703 | match dispatch_event { |
| 1704 | EpollDispatch::Unknown => { |
| 1705 | let event = event.data; |
| 1706 | warn!("Unknown VMM loop event: {event}"); |
| 1707 | } |
| 1708 | EpollDispatch::Exit => { |
| 1709 | info!("VM exit event"); |
| 1710 | // Consume the event. |
| 1711 | self.exit_evt.read().map_err(Error::EventFdRead)?; |
| 1712 | self.vmm_shutdown().map_err(Error::VmmShutdown)?; |
| 1713 | |
| 1714 | break 'outer; |
| 1715 | } |
| 1716 | EpollDispatch::Reset => { |
| 1717 | info!("VM reset event"); |
| 1718 | // Consume the event. |
| 1719 | self.reset_evt.read().map_err(Error::EventFdRead)?; |
| 1720 | self.vm_reboot().map_err(Error::VmReboot)?; |
| 1721 | } |
| 1722 | EpollDispatch::GuestExit => { |
| 1723 | info!("VM guest exit event"); |
| 1724 | self.guest_exit_evt.read().map_err(Error::EventFdRead)?; |
| 1725 | if self.no_shutdown { |
| 1726 | self.vm_shutdown().map_err(Error::VmShutdown)?; |
| 1727 | } else { |
| 1728 | self.vmm_shutdown().map_err(Error::VmmShutdown)?; |
| 1729 | break 'outer; |
| 1730 | } |
no test coverage detected