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 {
|
fn supports_presentation_feedback(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_input_fds(&self) -> Vec<Rc<OwnedFd>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,18 @@ impl Backend for MetalBackend {
|
||||||
fn supports_presentation_feedback(&self) -> bool {
|
fn supports_presentation_feedback(&self) -> bool {
|
||||||
true
|
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> {
|
fn dup_fd(fd: c::c_int) -> Result<Rc<OwnedFd>, MetalError> {
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,16 @@ use {
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
utils::oserror::OsError,
|
utils::{
|
||||||
|
clone3::{Forked, fork_with_pidfd},
|
||||||
|
errorfmt::ErrorFmt,
|
||||||
|
oserror::OsError,
|
||||||
|
},
|
||||||
wire::{JayReexecId, jay_reexec::*},
|
wire::{JayReexecId, jay_reexec::*},
|
||||||
},
|
},
|
||||||
std::{cell::RefCell, rc::Rc},
|
std::{array::from_mut, cell::RefCell, rc::Rc},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
uapi::UstrPtr,
|
uapi::{OwnedFd, UstrPtr, c, close_range, dup2, pipe2},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct JayReexec {
|
pub struct JayReexec {
|
||||||
|
|
@ -26,6 +30,60 @@ impl JayReexec {
|
||||||
msg,
|
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 {
|
impl JayReexecRequestHandler for JayReexec {
|
||||||
|
|
@ -43,6 +101,7 @@ impl JayReexecRequestHandler for JayReexec {
|
||||||
for arg in &*args {
|
for arg in &*args {
|
||||||
args2.push(&**arg);
|
args2.push(&**arg);
|
||||||
}
|
}
|
||||||
|
let _drop_after_exec = self.delay_close_input_fd();
|
||||||
if let Err(e) = uapi::execvp(req.path, &args2) {
|
if let Err(e) = uapi::execvp(req.path, &args2) {
|
||||||
self.send_failed(&OsError(e.0).to_string());
|
self.send_failed(&OsError(e.0).to_string());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue