diff --git a/Cargo.toml b/Cargo.toml index 19510f92..3a917aa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ debug = ["iced/debug"] # Enables pipewire support in ashpd, if ashpd is enabled pipewire = ["ashpd?/pipewire"] # Enables process spawning helper -process = ["dep:nix"] +process = ["dep:libc", "dep:rustix"] # Use rfd for file dialogs rfd = ["dep:rfd"] # Enables desktop files helpers @@ -83,10 +83,11 @@ derive_setters = "0.1.5" fraction = "0.14.0" image = { version = "0.25.1", optional = true } lazy_static = "1.4.0" +libc = { version = "0.2.155", optional = true } mime = { version = "0.3.17", optional = true } -nix = { version = "0.27", features = ["process"], optional = true } palette = "0.7.3" rfd = { version = "0.14.0", optional = true } +rustix = { version = "0.38.34", features = ["pipe", "process"], optional = true } serde = { version = "1.0.180", features = ["derive"] } slotmap = "1.0.6" textdistance = { version = "1.0.2", optional = true } diff --git a/src/process.rs b/src/process.rs index 1f58531a..a179af78 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,31 +1,50 @@ +use std::fs::File; +use std::io; 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) { +pub fn spawn(mut command: Command) -> Option { command .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()); - unsafe { - match fork() { - Ok(ForkResult::Parent { child }) => { - let _res = waitpid(Some(child), None); + let Ok((read, write)) = rustix::pipe::pipe_with(rustix::pipe::PipeFlags::CLOEXEC) else { + return None; + }; + + match unsafe { libc::fork() } { + // Parent process + child @ 1.. => { + let child = rustix::process::Pid::from_raw(child).unwrap(); + let _res = rustix::process::waitpid(Some(child), rustix::process::WaitOptions::empty()); + // Read PID from pipe + let mut bytes = [0; 4]; + if rustix::io::read(read, &mut bytes) == Ok(4) { + Some(u32::from_ne_bytes(bytes)) + } else { + None + } + } + + // Child process + 0 => { + let _res = rustix::process::setsid(); + if let Ok(child) = command.spawn() { + // Write PID to pipe + let _ = rustix::io::write(write, &child.id().to_ne_bytes()); } - Ok(ForkResult::Child) => { - let _res = nix::unistd::setsid(); - let _res = command.spawn(); + exit(0) + } - exit(0); - } + ..=-1 => { + println!( + "failed to fork and spawn command: {}", + io::Error::last_os_error() + ); - Err(why) => { - println!("failed to fork and spawn command: {}", why.desc()); - } + None } } }