Use rustix/libc instead of nix; use pipe to capture double-fork pid
`rustix` and `libc` are already in the dependency tree, and `rustix` follows IO safety rules, so use those. We can use a pipe to get the PID of the double-forked process.
This commit is contained in:
parent
a5996b4e90
commit
fe035e37b0
2 changed files with 38 additions and 18 deletions
|
|
@ -24,7 +24,7 @@ debug = ["iced/debug"]
|
||||||
# Enables pipewire support in ashpd, if ashpd is enabled
|
# Enables pipewire support in ashpd, if ashpd is enabled
|
||||||
pipewire = ["ashpd?/pipewire"]
|
pipewire = ["ashpd?/pipewire"]
|
||||||
# Enables process spawning helper
|
# Enables process spawning helper
|
||||||
process = ["dep:nix"]
|
process = ["dep:libc", "dep:rustix"]
|
||||||
# Use rfd for file dialogs
|
# Use rfd for file dialogs
|
||||||
rfd = ["dep:rfd"]
|
rfd = ["dep:rfd"]
|
||||||
# Enables desktop files helpers
|
# Enables desktop files helpers
|
||||||
|
|
@ -83,10 +83,11 @@ derive_setters = "0.1.5"
|
||||||
fraction = "0.14.0"
|
fraction = "0.14.0"
|
||||||
image = { version = "0.25.1", optional = true }
|
image = { version = "0.25.1", optional = true }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
libc = { version = "0.2.155", optional = true }
|
||||||
mime = { version = "0.3.17", optional = true }
|
mime = { version = "0.3.17", optional = true }
|
||||||
nix = { version = "0.27", features = ["process"], optional = true }
|
|
||||||
palette = "0.7.3"
|
palette = "0.7.3"
|
||||||
rfd = { version = "0.14.0", optional = true }
|
rfd = { version = "0.14.0", optional = true }
|
||||||
|
rustix = { version = "0.38.34", features = ["pipe", "process"], optional = true }
|
||||||
serde = { version = "1.0.180", features = ["derive"] }
|
serde = { version = "1.0.180", features = ["derive"] }
|
||||||
slotmap = "1.0.6"
|
slotmap = "1.0.6"
|
||||||
textdistance = { version = "1.0.2", optional = true }
|
textdistance = { version = "1.0.2", optional = true }
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,50 @@
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
use std::process::{exit, Command, Stdio};
|
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.
|
/// 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<u32> {
|
||||||
command
|
command
|
||||||
.stdin(Stdio::null())
|
.stdin(Stdio::null())
|
||||||
.stdout(Stdio::null())
|
.stdout(Stdio::null())
|
||||||
.stderr(Stdio::null());
|
.stderr(Stdio::null());
|
||||||
|
|
||||||
unsafe {
|
let Ok((read, write)) = rustix::pipe::pipe_with(rustix::pipe::PipeFlags::CLOEXEC) else {
|
||||||
match fork() {
|
return None;
|
||||||
Ok(ForkResult::Parent { child }) => {
|
};
|
||||||
let _res = waitpid(Some(child), 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) => {
|
exit(0)
|
||||||
let _res = nix::unistd::setsid();
|
}
|
||||||
let _res = command.spawn();
|
|
||||||
|
|
||||||
exit(0);
|
..=-1 => {
|
||||||
}
|
println!(
|
||||||
|
"failed to fork and spawn command: {}",
|
||||||
|
io::Error::last_os_error()
|
||||||
|
);
|
||||||
|
|
||||||
Err(why) => {
|
None
|
||||||
println!("failed to fork and spawn command: {}", why.desc());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue