mirror of
https://gitlab.com/marcandre.lureau/qemu-display.git
synced 2024-12-22 05:35:20 +00:00
Fix usbredir cleanups on stop
We need to kick all the helper threads to avoid "leaking" them. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
b5bb98ad0e
commit
36d9aa07ab
@ -25,6 +25,7 @@ struct InnerHandler {
|
||||
stream_thread: JoinHandle<()>,
|
||||
ctxt: rusb::Context,
|
||||
ctxt_thread: Option<JoinHandle<()>>,
|
||||
event: (UnixStream, UnixStream),
|
||||
quit: bool,
|
||||
}
|
||||
|
||||
@ -36,7 +37,7 @@ struct Handler {
|
||||
impl DeviceHandler for Handler {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
let read = match fd_poll_readable(inner.stream.as_raw_fd(), false) {
|
||||
let read = match fd_poll_readable(inner.stream.as_raw_fd(), None) {
|
||||
Ok(true) => {
|
||||
let read = inner.stream.read(buf);
|
||||
if let Ok(0) = read {
|
||||
@ -99,17 +100,17 @@ impl Handler {
|
||||
};
|
||||
|
||||
let (stream, peer) = UnixStream::pair()?;
|
||||
chardev.proxy.register(dbg!(peer.as_raw_fd()).into()).await?;
|
||||
chardev.proxy.register(peer.as_raw_fd().into()).await?;
|
||||
|
||||
let c = ctxt.clone();
|
||||
let stream_fd = stream.as_raw_fd();
|
||||
dbg!(stream_fd);
|
||||
// really annoying libusb/usbredir APIs...
|
||||
let event = UnixStream::pair()?;
|
||||
let event_fd = event.1.as_raw_fd();
|
||||
let stream_thread = std::thread::spawn(move || loop {
|
||||
let ret = fd_poll_readable(stream_fd, true);
|
||||
let ret = fd_poll_readable(stream_fd, Some(event_fd));
|
||||
c.interrupt_handle_events();
|
||||
if ret.is_err() {
|
||||
dbg!();
|
||||
break;
|
||||
}
|
||||
});
|
||||
@ -119,6 +120,7 @@ impl Handler {
|
||||
device_fd,
|
||||
stream,
|
||||
stream_thread,
|
||||
event,
|
||||
quit: false,
|
||||
ctxt: ctxt.clone(),
|
||||
ctxt_thread: Default::default(),
|
||||
@ -130,10 +132,9 @@ impl Handler {
|
||||
let inner = handler.inner.clone();
|
||||
let ctxt_thread = std::thread::spawn(move || loop {
|
||||
if inner.lock().unwrap().quit {
|
||||
dbg!();
|
||||
break;
|
||||
}
|
||||
if let Ok(true) = fd_poll_readable(stream_fd, false) {
|
||||
if let Ok(true) = fd_poll_readable(stream_fd, None) {
|
||||
redirdev.read_peer().unwrap();
|
||||
}
|
||||
if redirdev.has_data_to_write() > 0 {
|
||||
@ -152,18 +153,13 @@ impl Handler {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InnerHandler {
|
||||
fn drop(&mut self) {
|
||||
//FIXME: for some reason close stream doesn't HUP qemu ??
|
||||
dbg!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Handler {
|
||||
fn drop(&mut self) {
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.quit = true;
|
||||
inner.ctxt.interrupt_handle_events();
|
||||
// stream will be dropped and stream_thread will kick context_thread
|
||||
inner.event.0.write(&[0]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,22 +235,30 @@ impl UsbRedir {
|
||||
}
|
||||
}
|
||||
|
||||
fn fd_poll_readable(fd: RawFd, wait: bool) -> std::io::Result<bool> {
|
||||
let mut fds = [libc::pollfd {
|
||||
fn fd_poll_readable(fd: RawFd, wait: Option<RawFd>) -> std::io::Result<bool> {
|
||||
let mut fds = vec![libc::pollfd {
|
||||
fd,
|
||||
events: libc::POLLIN|libc::POLLHUP,
|
||||
revents: 0,
|
||||
}];
|
||||
let ret = unsafe { libc::poll(fds.as_mut_ptr(), 1, if wait { -1 } else { 0 }) };
|
||||
if ret > 0 {
|
||||
if fds[0].revents & libc::POLLHUP != 0 {
|
||||
Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, "hup"))
|
||||
} else {
|
||||
Ok(fds[0].revents & libc::POLLIN != 0)
|
||||
}
|
||||
if let Some(wait) = wait {
|
||||
fds.push(libc::pollfd {
|
||||
fd: wait,
|
||||
events: libc::POLLIN|libc::POLLHUP,
|
||||
revents: 0,
|
||||
});
|
||||
}
|
||||
let ret = unsafe { libc::poll(fds.as_mut_ptr(),
|
||||
fds.len() as _,
|
||||
if wait.is_some() { -1 } else { 0 }) };
|
||||
if ret < 0 {
|
||||
Err(std::io::Error::last_os_error())
|
||||
} else if ret == 0 {
|
||||
Ok(false)
|
||||
} else if fds[0].revents & libc::POLLHUP != 0 ||
|
||||
(wait.is_some() && fds[1].revents & libc::POLLIN != 0) {
|
||||
Err(std::io::Error::new(std::io::ErrorKind::BrokenPipe, "hup"))
|
||||
} else {
|
||||
Err(std::io::Error::last_os_error())
|
||||
Ok(fds[0].revents & libc::POLLIN != 0)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user