use std::io; /// Global process group manager — one per application lifetime. /// /// On Windows, owns a Job Object with KILL_ON_JOB_CLOSE. /// On Linux, configures the process as a child subreaper. /// On macOS, no-op (process groups handle cleanup). pub trait ProcessGroupManager: Send + Sync { /// Initialize platform-specific parent process configuration. fn init(&self) -> Result<(), io::Error>; /// Create a lifecycle handle for managing a child process. fn create_lifecycle(&self) -> Box; } /// Per-child process lifecycle manager. /// /// All methods are synchronous — OS signal/handle calls are instant. /// For timeout-based shutdown, use the free functions in the `shutdown` module. pub trait ProcessLifecycle: Send + Sync { /// Configure a std::process::Command before spawning. /// Sets platform-specific flags (process group, creation flags, pre_exec hooks). fn configure_command(&self, cmd: &mut std::process::Command); /// Configure a tokio::process::Command before spawning. #[cfg(feature = "tokio")] fn configure_async_command(&self, cmd: &mut tokio::process::Command); /// Register a spawned child with the lifecycle manager. /// Must be called immediately after spawn with the child's PID. fn register_child(&self, pid: u32) -> Result<(), io::Error>; /// Send a graceful shutdown signal to the process (and its tree). /// Windows: CTRL_BREAK_EVENT. Unix: SIGTERM to process group. fn send_shutdown_signal(&self, pid: u32) -> Result<(), io::Error>; /// Forcefully kill the process (and its tree). /// Windows: TerminateProcess. Unix: SIGKILL to process group. fn send_kill_signal(&self, pid: u32) -> Result<(), io::Error>; }