diff --git a/crates/pikl/src/handler.rs b/crates/pikl/src/handler.rs index 4c912e3..8b45ebf 100644 --- a/crates/pikl/src/handler.rs +++ b/crates/pikl/src/handler.rs @@ -156,15 +156,49 @@ async fn run_handler_process( // Close stdin to signal the child drop(stdin_writer); - // Wait briefly for the reader to finish + // Wait up to 1s for child to exit after EOF + let exited = tokio::time::timeout( + std::time::Duration::from_secs(1), + child.wait(), + ) + .await + .is_ok(); + + if !exited { + // Send SIGTERM on Unix, then wait another second + #[cfg(unix)] + { + if let Some(pid) = child.id() { + // SAFETY: pid is valid (child is still running), SIGTERM is + // a standard signal. kill() returns 0 on success or -1 on + // error, which we ignore (child may have exited between the + // check and the signal). + unsafe { + libc::kill(pid as libc::pid_t, libc::SIGTERM); + } + } + let termed = tokio::time::timeout( + std::time::Duration::from_secs(1), + child.wait(), + ) + .await + .is_ok(); + if !termed { + let _ = child.kill().await; + } + } + #[cfg(not(unix))] + { + let _ = child.kill().await; + } + } + + // Wait for the reader to finish let _ = tokio::time::timeout( std::time::Duration::from_secs(2), reader_handle, ) .await; - // Kill child if still running - let _ = child.kill().await; - Ok(()) }