1
0
Fork 0
forked from wry/wry

xwayland: use io_uring to prevent lockups

See https://gitlab.freedesktop.org/wayland/wayland/-/issues/296
This commit is contained in:
Julian Orth 2022-05-11 21:45:15 +02:00
parent 5573b2a1b7
commit 285724b4f1
13 changed files with 1173 additions and 34 deletions

View file

@ -58,7 +58,10 @@ use {
},
ahash::{AHashMap, AHashSet},
bstr::ByteSlice,
futures_util::{select, FutureExt},
futures_util::{
future::{self, Either},
pin_mut, select, FutureExt,
},
smallvec::SmallVec,
std::{
borrow::Cow,
@ -250,7 +253,7 @@ pub struct Wm {
struct PendingTransfer {
mime_type: u32,
fd: AsyncFd,
fd: Rc<OwnedFd>,
}
const TEXT_PLAIN_UTF_8: &str = "text/plain;charset=utf-8";
@ -649,7 +652,6 @@ impl Wm {
}
Some(r) => r,
};
let name = mt.clone();
let mt = match self.mime_type_to_atom(mt).await {
Ok(mt) => mt,
Err(e) => {
@ -802,24 +804,6 @@ impl Wm {
return;
}
};
{
let res = OsError::tri(|| {
let fl = uapi::fcntl_getfl(fd.raw())?;
uapi::fcntl_setfl(fd.raw(), fl | c::O_NONBLOCK)?;
Ok(())
});
if let Err(e) = res {
log::error!("Could not set file description flags: {}", ErrorFmt(e));
return;
}
}
let fd = match self.state.eng.fd(&fd) {
Ok(afd) => afd,
Err(e) => {
log::error!("Could not create async fd: {}", ErrorFmt(e));
return;
}
};
let cs = ConvertSelection {
requestor: sd.win.get(),
selection: sd.selection.get(),
@ -1709,8 +1693,8 @@ impl Wm {
let transfer = XToWaylandTransfer {
id,
data: data.clone(),
pos: 0,
fd: transfer.fd,
state: self.state.clone(),
shared: self.shared.clone(),
};
self.shared
@ -2394,24 +2378,38 @@ impl Wm {
struct XToWaylandTransfer {
id: u64,
data: Rc<Vec<u8>>,
pos: usize,
fd: AsyncFd,
fd: Rc<OwnedFd>,
state: Rc<State>,
shared: Rc<XwmShared>,
}
impl XToWaylandTransfer {
async fn run(mut self) {
while self.pos < self.data.len() {
match uapi::write(self.fd.raw(), &self.data[self.pos..]) {
Ok(n) => self.pos += n,
Err(Errno(c::EAGAIN)) => {
if let Err(e) = self.fd.writable().await {
log::error!("Could not wait for fd to become writable: {}", ErrorFmt(e));
async fn run(self) {
let timeout = match self.state.eng.timeout(5000) {
Ok(to) => to,
Err(e) => {
log::error!("Could not create a timeout: {}", ErrorFmt(e));
return;
}
};
pin_mut!(timeout);
let mut pos = 0;
while pos < self.data.len() {
let f1 = self
.state
.io_uring
.write(&self.fd, &self.data, pos, self.data.len() - pos);
pin_mut!(f1);
match future::select(f1, &mut timeout).await {
Either::Left((res, _)) => match res {
Ok(n) => pos += n,
Err(e) => {
log::error!("Could not write to wayland client: {}", ErrorFmt(e));
break;
}
}
Err(e) => {
log::error!("Could not write to wayland client: {}", ErrorFmt(e));
},
Either::Right(_) => {
log::error!("Transfer timed out");
break;
}
}