mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
Use double-fork when spawning subprocesses
Fixes https://github.com/YaLTeR/niri/issues/10
This commit is contained in:
+2
-6
@@ -1,5 +1,3 @@
|
||||
use std::process::Command;
|
||||
|
||||
use smithay::backend::input::{
|
||||
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event,
|
||||
GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _,
|
||||
@@ -19,7 +17,7 @@ use smithay::wayland::tablet_manager::{TabletDescriptor, TabletSeatTrait};
|
||||
|
||||
use crate::config::{Action, Config, Modifiers};
|
||||
use crate::niri::State;
|
||||
use crate::utils::get_monotonic_time;
|
||||
use crate::utils::{get_monotonic_time, spawn};
|
||||
|
||||
pub enum CompositorMod {
|
||||
Super,
|
||||
@@ -149,9 +147,7 @@ impl State {
|
||||
}
|
||||
Action::Spawn(command) => {
|
||||
if let Some((command, args)) = command.split_first() {
|
||||
if let Err(err) = Command::new(command).args(args).spawn() {
|
||||
warn!("error spawning {command}: {err}");
|
||||
}
|
||||
spawn(command, args);
|
||||
}
|
||||
}
|
||||
Action::Screenshot => {
|
||||
|
||||
+2
-3
@@ -25,6 +25,7 @@ use portable_atomic::Ordering;
|
||||
use smithay::reexports::calloop::EventLoop;
|
||||
use smithay::reexports::wayland_server::Display;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use utils::spawn;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
@@ -76,9 +77,7 @@ fn main() {
|
||||
let mut data = LoopData { display, state };
|
||||
|
||||
if let Some((command, args)) = cli.command.split_first() {
|
||||
if let Err(err) = std::process::Command::new(command).args(args).spawn() {
|
||||
warn!("error spawning command: {err:?}");
|
||||
}
|
||||
spawn(command, args);
|
||||
}
|
||||
|
||||
event_loop
|
||||
|
||||
+50
-1
@@ -1,6 +1,9 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::{self, Read};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
@@ -107,3 +110,49 @@ pub fn make_screenshot_path() -> anyhow::Result<PathBuf> {
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// Spawns the command to run independently of the compositor.
|
||||
pub fn spawn(command: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>) {
|
||||
let _span = tracy_client::span!();
|
||||
|
||||
let command = command.as_ref();
|
||||
|
||||
let mut process = Command::new(command);
|
||||
process
|
||||
.args(args)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null());
|
||||
|
||||
// Double-fork to avoid having to waitpid the child.
|
||||
unsafe {
|
||||
process.pre_exec(|| {
|
||||
match libc::fork() {
|
||||
-1 => return Err(io::Error::last_os_error()),
|
||||
0 => (),
|
||||
_ => libc::_exit(0),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
let mut child = match process.spawn() {
|
||||
Ok(child) => child,
|
||||
Err(err) => {
|
||||
warn!("error spawning {command:?}: {err:?}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match child.wait() {
|
||||
Ok(status) => {
|
||||
if !status.success() {
|
||||
warn!("child did not exit successfully: {status:?}");
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("error waiting for child: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user