diff --git a/src/client.rs b/src/client.rs index 9fd49a48f..3781cd49 100644 --- a/src/client.rs +++ b/src/client.rs @@ -19,6 +19,7 @@ use { numcell::NumCell, pending_serial::PendingSerial, pid_info::{PidInfo, get_pid_info, get_socket_creds}, + pidfd_send_signal::pidfd_send_signal, }, wire::WlRegistryId, }, @@ -251,6 +252,13 @@ impl Drop for ClientHolder { self.data.surfaces_by_xwayland_serial.clear(); self.data.remove_activation_tokens(); self.data.commit_timelines.clear(); + if self.data.is_xwayland { + if let Some(pidfd) = self.data.state.xwayland.pidfd.get() { + if let Err(e) = pidfd_send_signal(&pidfd, c::SIGKILL) { + log::error!("Could not kill Xwayland: {}", ErrorFmt(e)); + } + } + } } } diff --git a/src/compositor.rs b/src/compositor.rs index 02d09347..7574f20f 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -218,6 +218,7 @@ fn start_compositor2( run_args, xwayland: XWaylandState { enabled: Cell::new(true), + pidfd: Default::default(), handler: Default::default(), queue: Default::default(), ipc_device_ids: Default::default(), diff --git a/src/state.rs b/src/state.rs index bc972c53..ff0a278d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -121,6 +121,7 @@ use { time::Duration, }, thiserror::Error, + uapi::OwnedFd, }; pub struct State { @@ -261,6 +262,7 @@ pub struct ScreenlockState { pub struct XWaylandState { pub enabled: Cell, + pub pidfd: CloneCell>>, pub handler: RefCell>>, pub queue: Rc>, pub ipc_device_ids: XIpcDeviceIds, diff --git a/src/utils.rs b/src/utils.rs index ba49cba1..bae62b58 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -43,6 +43,7 @@ pub mod oserror; pub mod page_size; pub mod pending_serial; pub mod pid_info; +pub mod pidfd_send_signal; pub mod process_name; pub mod ptr_ext; pub mod queue; diff --git a/src/utils/pidfd_send_signal.rs b/src/utils/pidfd_send_signal.rs new file mode 100644 index 00000000..74fdeec7 --- /dev/null +++ b/src/utils/pidfd_send_signal.rs @@ -0,0 +1,23 @@ +use { + crate::utils::oserror::OsError, + c::{c_int, syscall}, + std::{ptr, rc::Rc}, + uapi::{ + OwnedFd, + c::{self, SYS_pidfd_send_signal, siginfo_t}, + map_err, + }, +}; + +pub fn pidfd_send_signal(pidfd: &Rc, signal: c_int) -> Result<(), OsError> { + let res = unsafe { + syscall( + SYS_pidfd_send_signal, + pidfd.raw(), + signal, + ptr::null_mut::(), + 0, + ) + }; + map_err!(res).map(drop).map_err(|e| e.into()) +} diff --git a/src/xwayland.rs b/src/xwayland.rs index 949b5f08..ab078f50 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -14,7 +14,9 @@ use { io_uring::IoUringError, state::State, user_session::import_environment, - utils::{buf::Buf, errorfmt::ErrorFmt, line_logger::log_lines, oserror::OsError}, + utils::{ + buf::Buf, errorfmt::ErrorFmt, line_logger::log_lines, on_drop::OnDrop, oserror::OsError, + }, wire::WlSurfaceId, xcon::XconError, xwayland::{ @@ -185,6 +187,10 @@ async fn run( state.update_xwayland_wire_scale(); state.ring.readable(&Rc::new(dfdread)).await?; state.xwayland.queue.clear(); + state.xwayland.pidfd.set(Some(pidfd.clone())); + let _remove_pidfd = OnDrop(|| { + state.xwayland.pidfd.take(); + }); { let shared = Rc::new(XwmShared::default()); let wm = match Wm::get(state, client, wm1, &shared).await {