diff --git a/Cargo.lock b/Cargo.lock index ca43a60..45c79cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -651,6 +651,7 @@ dependencies = [ "itertools 0.11.0", "libcosmic", "log", + "nix 0.26.4", "notify", "once_cell", "pretty_env_logger", diff --git a/Cargo.toml b/Cargo.toml index 4f7f073..433e5ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ itertools = "0.11" freedesktop-icons = "0.2.4" current_locale = "0.1.1" url = "2.4" +nix = "0.26" [profile.release] lto = "thin" diff --git a/src/app.rs b/src/app.rs index 64ed69c..be92036 100644 --- a/src/app.rs +++ b/src/app.rs @@ -239,7 +239,7 @@ impl cosmic::Application for CosmicAppLibrary { Message::ActivationToken(token, exec) => { let mut exec = shlex::Shlex::new(&exec); let mut cmd = match exec.next() { - Some(cmd) if !cmd.contains("=") => tokio::process::Command::new(cmd), + Some(cmd) if !cmd.contains("=") => std::process::Command::new(cmd), _ => return Command::none(), }; for arg in exec { @@ -252,7 +252,9 @@ impl cosmic::Application for CosmicAppLibrary { cmd.env("XDG_ACTIVATION_TOKEN", token.clone()); cmd.env("DESKTOP_STARTUP_ID", token); } - let _ = cmd.spawn(); + tokio::task::spawn_blocking(|| { + crate::process::spawn(cmd); + }); return self.update(Message::Hide); } Message::SelectGroup(i) => { diff --git a/src/main.rs b/src/main.rs index f8b5e7b..b004ef8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod config; mod app; mod app_group; mod localize; +pub mod process; mod subscriptions; mod widgets; diff --git a/src/process.rs b/src/process.rs new file mode 100644 index 0000000..1f58531 --- /dev/null +++ b/src/process.rs @@ -0,0 +1,31 @@ +use std::process::{exit, Command, Stdio}; + +use nix::sys::wait::waitpid; +use nix::unistd::{fork, ForkResult}; + +/// Performs a double fork with setsid to spawn and detach a command. +pub fn spawn(mut command: Command) { + command + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + + unsafe { + match fork() { + Ok(ForkResult::Parent { child }) => { + let _res = waitpid(Some(child), None); + } + + Ok(ForkResult::Child) => { + let _res = nix::unistd::setsid(); + let _res = command.spawn(); + + exit(0); + } + + Err(why) => { + println!("failed to fork and spawn command: {}", why.desc()); + } + } + } +}