// Child-process spawning that does not leave zombies behind.
//
// A dropped `Child` is never waited on, so every launched application stays
// in the process table as `<defunct>` after it exits — the launcher can fill
// the table over a session. Each spawn gets a short-lived thread that blocks
// in `wait()` until the child is gone.

use std::io;
use std::process::Command;

pub fn spawn_reaped( cmd: &mut Command ) -> io::Result<u32>
{
	let mut child = cmd.spawn()?;
	let pid = child.id();
	// Naming the thread keeps it identifiable in a debugger; it costs one
	// blocked thread per running child, which is what `wait()` requires
	// without a SIGCHLD handler.
	let _ = std::thread::Builder::new()
		.name( format!( "reap-{pid}" ) )
		.spawn( move || { let _ = child.wait(); } );
	Ok( pid )
}
