@@ -14,7 +14,7 @@ use tracing::{debug, instrument, warn};
1414#[ cfg( unix) ]
1515use 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) ]
1919use 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