1
0
Fork 0
forked from wry/wry

io: use io_uring for all io

There should no longer be any

- read
- write
- connect
- sendmsg
- recvmsg
- accept

calls in the codebase. Previously we were using a mix of io_uring and
these calls which had some negative effects: Since we were using the old
system calls, we had to set the file descriptors to non-blocking. But
our io_uring code did not handle EAGAIN. This lead to programs sometimes
being killed when the wayland IO was actually blocking.

Now all file descriptors are set to blocking, but io_uring makes it
non-blocking from our perspective. The one exception are evdev files
because they are read via libinput and libinput uses the old system
calls.
This commit is contained in:
Julian Orth 2022-12-31 17:55:58 +01:00
parent 2db0ee8995
commit 9812a02f87
55 changed files with 900 additions and 672 deletions

View file

@ -20,7 +20,7 @@ use {
WlSurface,
},
},
io_uring::{IoUring, IoUringError, TaskResultExt},
io_uring::{IoUring, IoUringError},
rect::Rect,
state::State,
time::Time,
@ -28,7 +28,7 @@ use {
utils::{
bitflags::BitflagsExt, buf::Buf, clonecell::CloneCell, copyhashmap::CopyHashMap,
errorfmt::ErrorFmt, linkedlist::LinkedList, numcell::NumCell, oserror::OsError,
rc_eq::rc_eq, tri::Try,
rc_eq::rc_eq,
},
wire::{WlDataDeviceId, WlSurfaceId, ZwpPrimarySelectionDeviceV1Id},
wire_xcon::{
@ -67,11 +67,11 @@ use {
std::{
borrow::Cow,
cell::{Cell, RefCell},
mem::{self, MaybeUninit},
mem::{self},
ops::{Deref, DerefMut},
rc::Rc,
},
uapi::{c, Errno, OwnedFd},
uapi::{c, OwnedFd},
};
atoms! {
@ -1607,15 +1607,6 @@ impl Wm {
break 'convert;
}
};
let res = OsError::tri(|| {
let fl = uapi::fcntl_getfl(rx.raw())?;
uapi::fcntl_setfl(rx.raw(), fl | c::O_NONBLOCK)?;
Ok(())
});
if let Err(e) = res {
log::error!("Could not make pipe nonblocking: {}", e);
break 'convert;
}
success = None;
receive_data_offer::<T>(&offer.offer, &mt, Rc::new(tx));
let id = self.transfer_ids.fetch_add(1);
@ -1726,7 +1717,7 @@ impl Wm {
let id = self.transfer_ids.fetch_add(1);
let transfer = XToWaylandTransfer {
id,
data: data.slice(..),
data: data.clone(),
fd: transfer.fd,
state: self.state.clone(),
shared: self.shared.clone(),
@ -2467,7 +2458,7 @@ impl XToWaylandTransfer {
.state
.ring
.write(&self.fd, self.data.slice(pos..), Some(timeout));
match res.await.merge() {
match res.await {
Ok(n) => pos += n,
Err(IoUringError::OsError(OsError(c::ECANCELED))) => {
log::error!("Transfer timed out");
@ -2499,10 +2490,10 @@ struct WaylandToXTransfer {
impl WaylandToXTransfer {
async fn run(self) {
let mut success = false;
let mut buf = Box::new([MaybeUninit::<u8>::uninit(); 1024]);
let mut buf = Buf::new(1024);
loop {
match uapi::read(self.fd.raw(), &mut buf[..]) {
Ok(n) if n.is_empty() => {
match self.ring.read(&self.fd, buf.clone()).await {
Ok(0) => {
success = true;
break;
}
@ -2513,19 +2504,13 @@ impl WaylandToXTransfer {
property: self.property,
ty: self.ty,
format: 8,
data: n,
data: &buf[..n],
};
if let Err(e) = self.c.call(&cp).await {
log::error!("Could not append data to property: {}", ErrorFmt(e));
break;
}
}
Err(Errno(c::EAGAIN)) => {
if let Err(e) = self.ring.readable(&self.fd).await {
log::error!("Could not wait for fd to become readable: {}", ErrorFmt(e));
break;
}
}
Err(e) => {
log::error!("Could not read from wayland client: {}", ErrorFmt(e));
break;