Merge pull request #439 from mahkoh/jorth/reexec
reexec: close evdev fds in a separate process
This commit is contained in:
commit
4970749924
3 changed files with 78 additions and 3 deletions
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue