Skip to content
This repository was archived by the owner on Oct 24, 2022. It is now read-only.

Commit f6b7e49

Browse files
committed
handler: send exit event when destructing
VhostUserHandler waits for all working thread to exit in drop(), but there's no mechanism to notify the working threads to exit. So add VhostUserHandler::send_exit_event() to notify working threads to exit. Signed-off-by: Liu Jiang <[email protected]>
1 parent 5dc5673 commit f6b7e49

File tree

2 files changed

+46
-22
lines changed

2 files changed

+46
-22
lines changed

src/event_loop.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
1010
use std::result;
1111

1212
use vm_memory::bitmap::Bitmap;
13+
use vmm_sys_util::eventfd::EventFd;
1314

1415
use super::{VhostUserBackend, Vring, GM};
1516

@@ -60,6 +61,7 @@ pub struct VringEpollHandler<S: VhostUserBackend<B>, B: Bitmap + 'static> {
6061
backend: S,
6162
vrings: Vec<Vring<GM<B>>>,
6263
thread_id: usize,
64+
exit_event_fd: Option<EventFd>,
6365
exit_event_id: Option<u16>,
6466
}
6567

@@ -72,33 +74,46 @@ impl<S: VhostUserBackend<B>, B: Bitmap + 'static> VringEpollHandler<S, B> {
7274
) -> VringEpollResult<Self> {
7375
let epoll_fd = epoll::create(true).map_err(VringEpollError::EpollCreateFd)?;
7476
let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
75-
let (exit_event_fd, exit_event_id) = match backend.exit_event(thread_id) {
77+
78+
let handler = match backend.exit_event(thread_id) {
7679
Some((exit_event_fd, exit_event_id)) => {
77-
(exit_event_fd.as_raw_fd(), Some(exit_event_id))
80+
epoll::ctl(
81+
epoll_file.as_raw_fd(),
82+
epoll::ControlOptions::EPOLL_CTL_ADD,
83+
exit_event_fd.as_raw_fd(),
84+
epoll::Event::new(epoll::Events::EPOLLIN, u64::from(exit_event_id)),
85+
)
86+
.map_err(VringEpollError::RegisterExitEvent)?;
87+
88+
VringEpollHandler {
89+
epoll_file,
90+
backend,
91+
vrings,
92+
thread_id,
93+
exit_event_fd: Some(exit_event_fd),
94+
exit_event_id: Some(exit_event_id),
95+
}
7896
}
79-
None => (-1, None),
97+
None => VringEpollHandler {
98+
epoll_file,
99+
backend,
100+
vrings,
101+
thread_id,
102+
exit_event_fd: None,
103+
exit_event_id: None,
104+
},
80105
};
81-
let handler = VringEpollHandler {
82-
epoll_file,
83-
backend,
84-
vrings,
85-
thread_id,
86-
exit_event_id,
87-
};
88-
89-
if let Some(exit_event_id) = exit_event_id {
90-
epoll::ctl(
91-
handler.epoll_file.as_raw_fd(),
92-
epoll::ControlOptions::EPOLL_CTL_ADD,
93-
exit_event_fd,
94-
epoll::Event::new(epoll::Events::EPOLLIN, u64::from(exit_event_id)),
95-
)
96-
.map_err(VringEpollError::RegisterExitEvent)?;
97-
}
98106

99107
Ok(handler)
100108
}
101109

110+
/// Send `exit event` to break the event loop.
111+
pub fn send_exit_event(&self) {
112+
if let Some(eventfd) = self.exit_event_fd.as_ref() {
113+
let _ = eventfd.write(1);
114+
}
115+
}
116+
102117
/// Register an event into the epoll fd.
103118
///
104119
/// When this event is later triggered, the backend implementation of `handle_event` will be

src/handler.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,17 @@ impl<S: VhostUserBackend<B> + Clone, B: Bitmap + Clone + Send + Sync> VhostUserH
132132
}
133133
}
134134

135-
impl<S: VhostUserBackend<B> + Clone, B: Bitmap> VhostUserHandler<S, B> {
135+
impl<S: VhostUserBackend<B>, B: Bitmap> VhostUserHandler<S, B> {
136136
pub(crate) fn get_epoll_handlers(&self) -> Vec<Arc<VringEpollHandler<S, B>>> {
137137
self.handlers.clone()
138138
}
139139

140+
pub(crate) fn send_exit_event(&self) {
141+
for handler in self.handlers.iter() {
142+
handler.send_exit_event();
143+
}
144+
}
145+
140146
fn vmm_va_to_gpa(&self, vmm_va: u64) -> VhostUserHandlerResult<u64> {
141147
for mapping in self.mappings.iter() {
142148
if vmm_va >= mapping.vmm_addr && vmm_va < mapping.vmm_addr + mapping.size {
@@ -148,7 +154,7 @@ impl<S: VhostUserBackend<B> + Clone, B: Bitmap> VhostUserHandler<S, B> {
148154
}
149155
}
150156

151-
impl<S: VhostUserBackend<B> + Clone, B: NewBitmap + Clone> VhostUserSlaveReqHandlerMut
157+
impl<S: VhostUserBackend<B>, B: NewBitmap + Clone> VhostUserSlaveReqHandlerMut
152158
for VhostUserHandler<S, B>
153159
{
154160
fn set_owner(&mut self) -> VhostUserResult<()> {
@@ -526,6 +532,9 @@ impl<S: VhostUserBackend<B> + Clone, B: NewBitmap + Clone> VhostUserSlaveReqHand
526532

527533
impl<S: VhostUserBackend<B>, B: Bitmap> Drop for VhostUserHandler<S, B> {
528534
fn drop(&mut self) {
535+
// Signal all working threads to exit.
536+
self.send_exit_event();
537+
529538
for thread in self.worker_threads.drain(..) {
530539
if let Err(e) = thread.join() {
531540
error!("Error in vring worker: {:?}", e);

0 commit comments

Comments
 (0)