Skip to content

Commit 2e06f72

Browse files
committed
Windows Fix
1 parent df10338 commit 2e06f72

File tree

3 files changed

+36
-15
lines changed

3 files changed

+36
-15
lines changed

Cargo.lock

Lines changed: 16 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ libc = "0.2" # For setpgid and signal constants
2222
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } # For logging setup
2323
tempfile = "3" # For creating temporary directories in examples/tests
2424
anyhow = "1.0" # For simple error handling in examples
25+
windows-sys = "0.59.0"
2526

2627
# Dependency on the library itself (needed for building examples within the workspace)
2728
# This line might not be strictly necessary if cargo automatically detects it,

src/lib.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use tracing::{debug, instrument, warn};
1414
#[cfg(unix)]
1515
use nix::sys::signal::{killpg, Signal};
1616
#[cfg(windows)]
17-
use windows::Win32::System::Threading::{OpenProcess, TerminateProcess, PROCESS_TERMINATE};
17+
use windows_sys::Win32::System::Threading::{OpenProcess, TerminateProcess, PROCESS_TERMINATE};
1818
#[cfg(unix)]
1919
use nix::unistd::Pid;
2020
#[cfg(windows)]
@@ -291,39 +291,39 @@ async fn handle_timeout_event(
291291
}
292292
Err(e) => {
293293
// ESRCH means the process group doesn't exist (likely all processes exited quickly)
294-
if e == nix::errno::Errno::ESRCH {
294+
return if e == nix::errno::Errno::ESRCH {
295295
warn!(pid = pid_u32, error = %e, "Failed to kill process group (ESRCH - likely already exited). Checking child status.");
296296
// Check if the *original* child process exited
297297
match child.try_wait() {
298298
Ok(Some(status)) => {
299299
debug!(pid = pid_u32, status = %status, "Original child had already exited before kill signal processed");
300-
return Ok(Some(status)); // Treat as natural exit
300+
Ok(Some(status)) // Treat as natural exit
301301
}
302302
Ok(None) => {
303303
debug!(pid = pid_u32, "Original child still running or uncollected after killpg failed (ESRCH).");
304304
// Proceed as if timeout kill was attempted.
305-
return Ok(None);
305+
Ok(None)
306306
}
307307
Err(wait_err) => {
308308
warn!(pid = pid_u32, error = %wait_err, "Error checking child status after failed killpg (ESRCH)");
309-
return Err(CommandError::Wait(wait_err));
309+
Err(CommandError::Wait(wait_err))
310310
}
311311
}
312312
} else {
313313
// Another error occurred during killpg (e.g., permissions EPERM)
314314
warn!(pid = pid_u32, pgid = pid.as_raw(), error = %e, "Failed to send kill signal to process group.");
315315
// Map nix::Error to std::io::Error for CommandError::Kill
316-
return Err(CommandError::Kill(std::io::Error::new(
316+
Err(CommandError::Kill(std::io::Error::new(
317317
std::io::ErrorKind::Other,
318318
format!("Failed to kill process group for PID {}: {}", pid_u32, e),
319-
)));
319+
)))
320320
}
321321
}
322322
}
323323
#[cfg(windows)]
324324
{
325-
use windows::Win32::Foundation::{CloseHandle, HANDLE};
326-
use windows::Win32::System::Threading::{OpenProcess, TerminateProcess, PROCESS_TERMINATE};
325+
use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
326+
use windows_sys::Win32::System::Threading::{OpenProcess, TerminateProcess, PROCESS_TERMINATE};
327327

328328
unsafe {
329329
// Open a handle to the process with termination privileges.
@@ -549,6 +549,7 @@ pub async fn run_command_with_timeout(
549549
// Take ownership to modify, then pass the modified command to spawn_command_and_setup_state
550550
let mut std_cmd = std::mem::replace(&mut command, StdCommand::new("")); // Take ownership temporarily
551551
unsafe {
552+
#[cfg(unix)]
552553
std_cmd.pre_exec(|| {
553554
// libc::setpgid(0, 0) makes the new process its own group leader.
554555
// Pass 0 for both pid and pgid to achieve this for the calling process.
@@ -559,6 +560,15 @@ pub async fn run_command_with_timeout(
559560
Err(std::io::Error::last_os_error())
560561
}
561562
});
563+
#[cfg(windows)]
564+
{
565+
use std::os::windows::process::CommandExt;
566+
// CREATE_NEW_PROCESS_GROUP makes the new process the root of a new process group.
567+
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
568+
std_cmd.creation_flags(CREATE_NEW_PROCESS_GROUP);
569+
}
570+
571+
562572
}
563573
// Put the modified command back for spawning
564574
command = std_cmd;

0 commit comments

Comments
 (0)