Commit 7c46c935996a
tarball1 file changed+29-3
@@ -3,7 +3,10 @@ use monolith_config::{Config, Mods, MoveMode};
33
use monolith_ipc::Command;44
use monolith_layout::{ExpandScope, WindowId};55
use smithay::input::keyboard::{Keysym, ModifiersState, xkb};6
-use std::process::Stdio;6
+use smithay::reexports::calloop::generic::Generic;7
+use smithay::reexports::calloop::{Interest, Mode, PostAction};8
+use std::os::fd::{FromRawFd, OwnedFd, RawFd};9
+use std::process::{Child, Stdio};710
811
pub struct Binds(Vec<(Mods, Keysym, Command)>);912
@@ -173,14 +176,37 @@ impl State {
173176
let token = self.launch_token();174177
cmd.env("XDG_ACTIVATION_TOKEN", &token)175178
.env("DESKTOP_STARTUP_ID", &token);176
- let mut child = cmd.spawn().map_err(|e| format!("{program}: {e}"))?;179
+ let child = cmd.spawn().map_err(|e| format!("{program}: {e}"))?;177180
tracing::info!(pid = child.id(), ?argv, "spawned");178181
let (output, tag) = self.launch_context();179182
self.services.launches.record(child.id(), output, tag);180
- std::thread::spawn(move || child.wait());183
+ self.reap_on_exit(child);181184
Ok(())182185
}183186
187
+ /// Each child gets a pidfd, since a SIGCHLD reaper would also steal the188
+ /// exit of smithay's Xwayland.189
+ fn reap_on_exit(&mut self, mut child: Child) {190
+ let raw = unsafe { libc::syscall(libc::SYS_pidfd_open, child.id() as libc::pid_t, 0) };191
+ if raw < 0 {192
+ std::thread::spawn(move || child.wait());193
+ return;194
+ }195
+ // SAFETY: pidfd_open returned a new fd that nothing else owns.196
+ let fd = unsafe { OwnedFd::from_raw_fd(raw as RawFd) };197
+ let mut child = Some(child);198
+ let source = Generic::new(fd, Interest::READ, Mode::Level);199
+ let inserted = self.core.handle.insert_source(source, move |_, _, _| {200
+ if let Some(mut c) = child.take() {201
+ let _ = c.wait();202
+ }203
+ Ok(PostAction::Remove)204
+ });205
+ if let Err(e) = inserted {206
+ tracing::debug!("cannot watch a spawned child: {e}");207
+ }208
+ }209
+184210
/// Swaps in a freshly parsed config. A broken file leaves the running185211
/// config untouched.186212
pub fn reload(&mut self) -> Result<(), String> {