diff --git a/Cargo.lock b/Cargo.lock index a3c75c3..1583bfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7292,6 +7292,7 @@ dependencies = [ "include_dir", "indexmap 2.2.6", "itertools 0.10.5", + "libc", "numbat", "once_cell", "open", diff --git a/rust/server/Cargo.toml b/rust/server/Cargo.toml index 830a15e..92cd34d 100644 --- a/rust/server/Cargo.toml +++ b/rust/server/Cargo.toml @@ -42,6 +42,9 @@ bytes = "1.6.0" scenario_runner = { path = "../scenario_runner", optional = true } itertools = "0.10.5" +[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] +libc = "0.2.153" + [target.'cfg(target_os = "linux")'.dependencies] freedesktop_entry_parser = "1.3" freedesktop-icons = "0.2" diff --git a/rust/server/src/plugins/applications/mod.rs b/rust/server/src/plugins/applications/mod.rs index 44f3640..bba4251 100644 --- a/rust/server/src/plugins/applications/mod.rs +++ b/rust/server/src/plugins/applications/mod.rs @@ -1,9 +1,8 @@ +use image::ImageFormat; +use image::imageops::FilterType; #[cfg(target_os = "linux")] mod linux; - -use image::ImageFormat; -use image::imageops::FilterType; #[cfg(target_os = "linux")] pub use linux::get_apps; diff --git a/rust/server/src/plugins/js/plugins/applications.rs b/rust/server/src/plugins/js/plugins/applications.rs index a229332..a47de89 100644 --- a/rust/server/src/plugins/js/plugins/applications.rs +++ b/rust/server/src/plugins/js/plugins/applications.rs @@ -1,8 +1,5 @@ -use std::path::Path; - use deno_core::op; use tokio::task::spawn_blocking; - use crate::plugins::applications::{DesktopEntry, get_apps}; #[op] @@ -15,9 +12,50 @@ fn open_application(command: Vec) -> anyhow::Result<()> { let path = &command[0]; let args = &command[1..]; - std::process::Command::new(Path::new(path)) - .args(args) - .spawn()?; + #[cfg(not(windows))] + spawn_detached(path, args)?; Ok(()) } + +#[cfg(not(windows))] +pub fn spawn_detached( + path: &str, + args: I, +) -> std::io::Result<()> +where + I: IntoIterator + Copy, + S: AsRef, +{ + // from https://github.com/alacritty/alacritty/blob/5abb4b73937b17fe501b9ca20b602950f1218b96/alacritty/src/daemon.rs#L65 + use std::os::unix::prelude::CommandExt; + use std::process::{Command, Stdio}; + + let mut command = Command::new(path); + + command + .args(args) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + + unsafe { + command + .pre_exec(|| { + match libc::fork() { + -1 => return Err(std::io::Error::last_os_error()), + 0 => (), + _ => libc::_exit(0), + } + + if libc::setsid() == -1 { + return Err(std::io::Error::last_os_error()); + } + + Ok(()) + }) + .spawn()? + .wait() + .map(|_| ()) + } +} \ No newline at end of file diff --git a/rust/server/src/plugins/mod.rs b/rust/server/src/plugins/mod.rs index 7420617..cc81832 100644 --- a/rust/server/src/plugins/mod.rs +++ b/rust/server/src/plugins/mod.rs @@ -416,7 +416,7 @@ impl ApplicationManager { } pub fn handle_open(&self, href: String) { - match open::that(&href) { + match open::that_detached(&href) { Ok(()) => tracing::info!("Opened '{}' successfully.", href), Err(err) => tracing::error!("An error occurred when opening '{}': {}", href, err), }