1
0
Fork 0
forked from wry/wry

shm: close client buffers in the cpu worker

This commit is contained in:
Julian Orth 2024-09-07 22:54:36 +02:00
parent d40e605f66
commit ece56d91d3
7 changed files with 79 additions and 16 deletions

View file

@ -353,9 +353,10 @@ impl Input {
async fn handle_keymap(&self, input: JayInputId) -> Vec<u8> { async fn handle_keymap(&self, input: JayInputId) -> Vec<u8> {
let data = Rc::new(RefCell::new(Vec::new())); let data = Rc::new(RefCell::new(Vec::new()));
jay_input::Keymap::handle(&self.tc, input, data.clone(), |d, map| { jay_input::Keymap::handle(&self.tc, input, data.clone(), |d, map| {
let mem = let mem = Rc::new(
Rc::new(ClientMem::new(&map.keymap, map.keymap_len as _, true, None).unwrap()) ClientMem::new(&map.keymap, map.keymap_len as _, true, None, None).unwrap(),
.offset(0); )
.offset(0);
mem.read(d.borrow_mut().deref_mut()).unwrap(); mem.read(d.borrow_mut().deref_mut()).unwrap();
}); });
self.tc.round_trip().await; self.tc.round_trip().await;

View file

@ -1,8 +1,12 @@
use { use {
crate::{client::Client, utils::vec_ext::VecExt}, crate::{
client::Client,
cpu_worker::{AsyncCpuWork, CpuJob, CpuWork, CpuWorker},
utils::vec_ext::VecExt,
},
std::{ std::{
cell::Cell, cell::Cell,
mem::MaybeUninit, mem::{ManuallyDrop, MaybeUninit},
ptr, ptr,
rc::Rc, rc::Rc,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{compiler_fence, Ordering},
@ -25,10 +29,11 @@ pub enum ClientMemError {
} }
pub struct ClientMem { pub struct ClientMem {
fd: Rc<OwnedFd>, fd: ManuallyDrop<Rc<OwnedFd>>,
failed: Cell<bool>, failed: Cell<bool>,
sigbus_impossible: bool, sigbus_impossible: bool,
data: *const [Cell<u8>], data: *const [Cell<u8>],
cpu: Option<Rc<CpuWorker>>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -44,6 +49,7 @@ impl ClientMem {
len: usize, len: usize,
read_only: bool, read_only: bool,
client: Option<&Client>, client: Option<&Client>,
cpu: Option<&Rc<CpuWorker>>,
) -> Result<Self, ClientMemError> { ) -> Result<Self, ClientMemError> {
let mut sigbus_impossible = false; let mut sigbus_impossible = false;
if let Ok(seals) = uapi::fcntl_get_seals(fd.raw()) { if let Ok(seals) = uapi::fcntl_get_seals(fd.raw()) {
@ -78,10 +84,11 @@ impl ClientMem {
} }
}; };
Ok(Self { Ok(Self {
fd: fd.clone(), fd: ManuallyDrop::new(fd.clone()),
failed: Cell::new(false), failed: Cell::new(false),
sigbus_impossible, sigbus_impossible,
data, data,
cpu: cpu.cloned(),
}) })
} }
@ -155,8 +162,17 @@ impl ClientMemOffset {
impl Drop for ClientMem { impl Drop for ClientMem {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { let fd = unsafe { ManuallyDrop::take(&mut self.fd) };
c::munmap(self.data as _, self.len()); if let Some(cpu) = &self.cpu {
let pending = cpu.submit(Box::new(CloseMemWork {
fd: Rc::try_unwrap(fd).ok(),
data: self.data,
}));
pending.detach();
} else {
unsafe {
c::munmap(self.data as _, self.len());
}
} }
} }
} }
@ -219,3 +235,30 @@ pub fn init() -> Result<(), ClientMemError> {
} }
} }
} }
struct CloseMemWork {
fd: Option<OwnedFd>,
data: *const [Cell<u8>],
}
unsafe impl Send for CloseMemWork {}
impl CpuJob for CloseMemWork {
fn work(&mut self) -> &mut dyn CpuWork {
self
}
fn completed(self: Box<Self>) {
// nothing
}
}
impl CpuWork for CloseMemWork {
fn run(&mut self) -> Option<Box<dyn AsyncCpuWork>> {
self.fd.take();
unsafe {
c::munmap(self.data as _, self.data.len());
}
None
}
}

View file

@ -140,7 +140,6 @@ pub enum CpuWorkerError {
} }
impl PendingJob { impl PendingJob {
#[expect(dead_code)]
pub fn detach(self) { pub fn detach(self) {
match self.job_data.state.get() { match self.job_data.state.get() {
PendingJobState::Waiting => { PendingJobState::Waiting => {

View file

@ -169,7 +169,14 @@ impl JayInput {
where where
F: FnOnce(&Rc<XkbKeymap>) -> Result<(), JayInputError>, F: FnOnce(&Rc<XkbKeymap>) -> Result<(), JayInputError>,
{ {
let cm = Rc::new(ClientMem::new(keymap, len as _, true, Some(&self.client))?).offset(0); let cm = Rc::new(ClientMem::new(
keymap,
len as _,
true,
Some(&self.client),
None,
)?)
.offset(0);
let mut map = vec![]; let mut map = vec![];
cm.read(&mut map)?; cm.read(&mut map)?;
self.or_error(|| { self.or_error(|| {

View file

@ -56,9 +56,15 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
if req.size > MAX_SIZE { if req.size > MAX_SIZE {
return Err(ZwpVirtualKeyboardV1Error::OversizedKeymap); return Err(ZwpVirtualKeyboardV1Error::OversizedKeymap);
} }
let client_mem = ClientMem::new(&req.fd, req.size as usize - 1, true, Some(&self.client)) let client_mem = ClientMem::new(
.map(Rc::new) &req.fd,
.map_err(ZwpVirtualKeyboardV1Error::MapKeymap)?; req.size as usize - 1,
true,
Some(&self.client),
None,
)
.map(Rc::new)
.map_err(ZwpVirtualKeyboardV1Error::MapKeymap)?;
let mut map = vec![]; let mut map = vec![];
client_mem client_mem
.offset(0) .offset(0)

View file

@ -34,7 +34,13 @@ impl WlShmPool {
Ok(Self { Ok(Self {
id, id,
client: client.clone(), client: client.clone(),
mem: CloneCell::new(Rc::new(ClientMem::new(&fd, len, false, Some(client))?)), mem: CloneCell::new(Rc::new(ClientMem::new(
&fd,
len,
false,
Some(client),
Some(&client.state.cpu_worker),
)?)),
fd, fd,
tracker: Default::default(), tracker: Default::default(),
version, version,
@ -86,6 +92,7 @@ impl WlShmPoolRequestHandler for WlShmPool {
req.size as usize, req.size as usize,
false, false,
Some(&self.client), Some(&self.client),
Some(&self.client.state.cpu_worker),
)?)); )?));
Ok(()) Ok(())
} }

View file

@ -149,7 +149,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
} }
fn read_keymap(fd: &Rc<OwnedFd>, size: usize) -> String { fn read_keymap(fd: &Rc<OwnedFd>, size: usize) -> String {
let client_mem = ClientMem::new(fd, size - 1, true, None).unwrap(); let client_mem = ClientMem::new(fd, size - 1, true, None, None).unwrap();
let client_mem = Rc::new(client_mem).offset(0); let client_mem = Rc::new(client_mem).offset(0);
let mut v = vec![]; let mut v = vec![];
client_mem.read(&mut v).unwrap(); client_mem.read(&mut v).unwrap();