fix(process): safely exit forked child after spawn
Co-Authored-By: Michael Murphy <michael@mmurphy.dev>
This commit is contained in:
parent
631c81b170
commit
5782cb927e
1 changed files with 16 additions and 7 deletions
|
|
@ -5,7 +5,7 @@
|
|||
use smol::io::AsyncReadExt;
|
||||
use std::io;
|
||||
use std::os::fd::OwnedFd;
|
||||
use std::process::{Command, Stdio, exit};
|
||||
use std::process::{Command, Stdio};
|
||||
#[cfg(feature = "tokio")]
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
|
|
@ -56,24 +56,33 @@ pub async fn spawn(mut command: Command) -> Option<u32> {
|
|||
|
||||
match unsafe { libc::fork() } {
|
||||
// Parent process
|
||||
1.. => {
|
||||
fork_pid @ 1..=i32::MAX => {
|
||||
// Drop copy of write end, then read PID from pipe
|
||||
drop(write);
|
||||
let pid = read_from_pipe(read).await;
|
||||
// wait to prevent zombie
|
||||
_ = rustix::process::wait(rustix::process::WaitOptions::empty());
|
||||
_ = rustix::process::waitpid(
|
||||
rustix::process::Pid::from_raw(fork_pid),
|
||||
rustix::process::WaitOptions::empty(),
|
||||
);
|
||||
pid
|
||||
}
|
||||
|
||||
// Child process
|
||||
0 => {
|
||||
let _res = rustix::process::setsid();
|
||||
if let Ok(child) = command.spawn() {
|
||||
let exit_status = if let Ok(child) = command.spawn() {
|
||||
// Write PID to pipe
|
||||
let _ = rustix::io::write(write, &child.id().to_be_bytes());
|
||||
}
|
||||
0
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
exit(0)
|
||||
// # Safety
|
||||
// Required for child fork to exit without affecting the parent.
|
||||
unsafe {
|
||||
libc::_exit(exit_status);
|
||||
}
|
||||
}
|
||||
|
||||
..=-1 => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue