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

@ -1,16 +1,15 @@
use {
crate::{
dbus::{incoming::handle_incoming, outgoing::handle_outgoing, DbusError, DbusSocket},
utils::{errorfmt::ErrorFmt, hex},
utils::{buf::Buf, errorfmt::ErrorFmt, hex},
},
std::{io::Write, rc::Rc},
uapi::{c, Errno},
std::{ops::Deref, rc::Rc},
};
pub(super) async fn handle_auth(socket: Rc<DbusSocket>) {
let mut auth = Auth {
socket: socket.clone(),
buf: Box::new([0; BUF_SIZE]),
buf: Buf::new(BUF_SIZE),
buf_start: 0,
buf_stop: 0,
};
@ -22,7 +21,7 @@ const BUF_SIZE: usize = 128;
struct Auth {
socket: Rc<DbusSocket>,
buf: Box<[u8; BUF_SIZE]>,
buf: Buf,
buf_start: usize,
buf_stop: usize,
}
@ -50,61 +49,77 @@ impl Auth {
async fn handle_auth(&mut self) -> Result<(), DbusError> {
let uid = hex::to_hex(&uapi::getuid().to_string());
let mut out_buf = Vec::new();
let _ = write!(out_buf, "\0AUTH EXTERNAL {}\r\n", uid);
self.write_buf(&mut out_buf).await?;
let mut out_buf = Buf::new(128);
{
let buf = out_buf
.write_fmt(format_args!("\0AUTH EXTERNAL {}\r\n", uid))
.unwrap();
self.write_buf(buf).await?;
}
let line = self.readline().await?;
let (cmd, _) = line_to_cmd(&line);
if cmd != "OK" {
return Err(DbusError::Auth);
}
let _ = write!(out_buf, "NEGOTIATE_UNIX_FD\r\n");
self.write_buf(&mut out_buf).await?;
{
let buf = out_buf
.write_fmt(format_args!("NEGOTIATE_UNIX_FD\r\n"))
.unwrap();
self.write_buf(buf).await?;
}
let line = self.readline().await?;
let (cmd, _) = line_to_cmd(&line);
if cmd != "AGREE_UNIX_FD" {
return Err(DbusError::UnixFd);
}
let _ = write!(out_buf, "BEGIN\r\n");
self.write_buf(&mut out_buf).await?;
{
let buf = out_buf.write_fmt(format_args!("BEGIN\r\n")).unwrap();
self.write_buf(buf).await?;
}
Ok(())
}
async fn readline(&mut self) -> Result<String, DbusError> {
let mut s = String::new();
loop {
for i in self.buf_start..self.buf_stop {
let c = self.buf[i % BUF_SIZE] as char;
s.push(c);
if c == '\n' {
self.buf_start = i + 1;
return Ok(s);
{
let buf = self.buf.deref();
for i in self.buf_start..self.buf_stop {
let c = buf[i % BUF_SIZE] as char;
s.push(c);
if c == '\n' {
self.buf_start = i + 1;
return Ok(s);
}
}
}
self.buf_start = 0;
self.buf_stop = 0;
match uapi::read(self.socket.fd.raw(), &mut self.buf[..]) {
Ok(n) => self.buf_stop = n.len(),
Err(Errno(c::EAGAIN)) => {
self.socket.ring.readable(&self.socket.fd).await?;
}
Err(e) => return Err(DbusError::ReadError(e.into())),
let res = self
.socket
.ring
.read(&self.socket.fd, self.buf.clone())
.await;
match res {
Ok(n) => self.buf_stop = n,
Err(e) => return Err(DbusError::ReadError(e)),
}
}
}
async fn write_buf(&mut self, buf: &mut Vec<u8>) -> Result<(), DbusError> {
async fn write_buf(&mut self, mut buf: Buf) -> Result<(), DbusError> {
let mut start = 0;
while start < buf.len() {
match uapi::write(self.socket.fd.raw(), &buf[start..]) {
let res = self
.socket
.ring
.write(&self.socket.fd, buf.slice(start..), None)
.await;
match res {
Ok(n) => start += n,
Err(Errno(c::EAGAIN)) => {
self.socket.ring.writable(&self.socket.fd).await?;
}
Err(e) => return Err(DbusError::WriteError(e.into())),
Err(e) => return Err(DbusError::WriteError(e)),
}
}
buf.clear();
Ok(())
}
}