// Fire-and-forget child processes that do not leave zombies behind.
//
// A dropped `Child` is never waited on, so short-lived helpers (brightnessctl
// on every brightness step, playerctl, grim) pile up as `<defunct>` entries
// for the rest of the session.

use std::process::{Child, Command};

/// Spawn `cmd` and reap it in the background. Errors are logged, not returned:
/// every caller here is best-effort.
pub fn detached(mut cmd: Command) {
    match cmd.spawn() {
        Ok(child) => reap(child),
        Err(e) => tracing::debug!("spawn failed: {e}"),
    }
}

/// Reap an already-spawned `child` in the background so it does not linger as
/// a `<defunct>` entry. Use when the caller kept the `Child` (e.g. to signal
/// it) and now wants to wait on it without blocking.
pub fn reap(mut child: Child) {
    let _ = std::thread::Builder::new()
        .name(format!("reap-{}", child.id()))
        .spawn(move || {
            let _ = child.wait();
        });
}
