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:
parent
2db0ee8995
commit
9812a02f87
55 changed files with 900 additions and 672 deletions
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue