1
0
Fork 0
forked from wry/wry

Merge pull request #439 from mahkoh/jorth/reexec

reexec: close evdev fds in a separate process
This commit is contained in:
mahkoh 2025-04-24 17:47:19 +02:00 committed by GitHub
commit 4970749924
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 3 deletions

View file

@ -60,6 +60,10 @@ pub trait Backend: Any {
fn supports_presentation_feedback(&self) -> bool {
false
}
fn get_input_fds(&self) -> Vec<Rc<OwnedFd>> {
vec![]
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]

View file

@ -277,6 +277,18 @@ impl Backend for MetalBackend {
fn supports_presentation_feedback(&self) -> bool {
true
}
fn get_input_fds(&self) -> Vec<Rc<OwnedFd>> {
let mut res = vec![];
for dev in &*self.device_holder.input_devices.borrow() {
if let Some(dev) = dev {
if let Some(fd) = dev.fd.get() {
res.push(fd);
}
}
}
res
}
}
fn dup_fd(fd: c::c_int) -> Result<Rc<OwnedFd>, MetalError> {

View file

@ -3,12 +3,16 @@ use {
client::{Client, ClientError},
leaks::Tracker,
object::{Object, Version},
utils::oserror::OsError,
utils::{
clone3::{Forked, fork_with_pidfd},
errorfmt::ErrorFmt,
oserror::OsError,
},
wire::{JayReexecId, jay_reexec::*},
},
std::{cell::RefCell, rc::Rc},
std::{array::from_mut, cell::RefCell, rc::Rc},
thiserror::Error,
uapi::UstrPtr,
uapi::{OwnedFd, UstrPtr, c, close_range, dup2, pipe2},
};
pub struct JayReexec {
@ -26,6 +30,60 @@ impl JayReexec {
msg,
});
}
fn delay_close_input_fd(&self) -> Option<OwnedFd> {
// It's 2025 and closing evdev fds is still abysmally slow.
let mut fds = self.client.state.backend.get().get_input_fds();
if fds.is_empty() {
return None;
}
macro_rules! pipe {
() => {
match pipe2(c::O_CLOEXEC) {
Ok(p) => p,
Err(e) => {
log::error!("Could not create pipe: {}", ErrorFmt(OsError::from(e)));
return None;
}
}
};
}
let (p1, c1) = pipe!();
let (c2, p2) = pipe!();
if let Ok(f) = fork_with_pidfd(false) {
if let Forked::Child { .. } = f {
drop(p2);
fds.sort_by_key(|fd| fd.raw());
let c2_dup = fds.last().unwrap().raw() + 1;
let c1_dup = c2_dup + 1;
let _ = dup2(c1.raw(), c1_dup);
let _ = dup2(c2.raw(), c2_dup);
for (idx, fd) in fds.iter().enumerate() {
let _ = dup2(fd.raw(), idx as _);
}
let c2_dup_dup = fds.len() as _;
let _ = dup2(c2_dup, c2_dup_dup);
let _ = close_range(c2_dup_dup as c::c_uint + 1, !0, 0);
let mut pollfd = c::pollfd {
fd: c2_dup_dup,
events: 0,
revents: 0,
};
let _ = uapi::poll(from_mut(&mut pollfd), -1);
unsafe {
c::_exit(0);
}
}
}
drop(c1);
let mut pollfd = c::pollfd {
fd: p1.raw(),
events: 0,
revents: 0,
};
let _ = uapi::poll(from_mut(&mut pollfd), -1);
Some(p2)
}
}
impl JayReexecRequestHandler for JayReexec {
@ -43,6 +101,7 @@ impl JayReexecRequestHandler for JayReexec {
for arg in &*args {
args2.push(&**arg);
}
let _drop_after_exec = self.delay_close_input_fd();
if let Err(e) = uapi::execvp(req.path, &args2) {
self.send_failed(&OsError(e.0).to_string());
}