@@ -27,7 +27,6 @@ use std::{
27
27
use portable_pty:: { native_pty_system, Child as PtyChild , MasterPty as PtyController } ;
28
28
use tokio:: {
29
29
io:: { AsyncBufRead , AsyncBufReadExt , BufReader } ,
30
- join,
31
30
process:: Command as TokioCommand ,
32
31
sync:: { mpsc, watch} ,
33
32
} ;
@@ -484,38 +483,19 @@ impl Child {
484
483
}
485
484
486
485
/// Perform a graceful shutdown of the `Child` process.
487
- pub async fn stop ( & self ) -> Option < ChildExit > {
488
- let mut watch = self . exit_channel . clone ( ) ;
489
-
490
- let ( _, code) = join ! {
491
- // if this fails, it's because the channel is dropped (toctou)
492
- // we can just ignore it
493
- self . command_channel. stop( ) ,
494
- async {
495
- watch. changed( ) . await . ok( ) ?;
496
- * watch. borrow( )
497
- }
498
- } ;
499
-
500
- code
486
+ pub async fn stop ( & mut self ) -> Option < ChildExit > {
487
+ // if this fails, it's because the channel is dropped (toctou)
488
+ // we can just ignore it
489
+ self . command_channel . stop ( ) . await . ok ( ) ;
490
+ self . wait ( ) . await
501
491
}
502
492
503
493
/// Kill the `Child` process immediately.
504
- pub async fn kill ( & self ) -> Option < ChildExit > {
505
- let mut watch = self . exit_channel . clone ( ) ;
506
-
507
- let ( _, code) = join ! {
508
- // if this fails, it's because the channel is dropped (toctou)
509
- // we can just ignore it
510
- self . command_channel. kill( ) ,
511
- async {
512
- // if this fails, it is because the watch receiver is dropped. just ignore it do a best-effort
513
- watch. changed( ) . await . ok( ) ;
514
- * watch. borrow( )
515
- }
516
- } ;
517
-
518
- code
494
+ pub async fn kill ( & mut self ) -> Option < ChildExit > {
495
+ // if this fails, it's because the channel is dropped (toctou)
496
+ // we can just ignore it
497
+ self . command_channel . kill ( ) . await . ok ( ) ;
498
+ self . wait ( ) . await
519
499
}
520
500
521
501
pub fn pid ( & self ) -> Option < u32 > {
@@ -734,7 +714,7 @@ impl ChildStateManager {
734
714
}
735
715
} ;
736
716
// ignore the send error, failure means the channel is dropped
737
- trace ! ( "sending child exit" ) ;
717
+ trace ! ( "sending child exit after shutdown " ) ;
738
718
self . exit_tx . send ( Some ( exit) ) . ok ( ) ;
739
719
drop ( controller) ;
740
720
}
@@ -1167,12 +1147,15 @@ mod test {
1167
1147
#[ test_case( false ) ]
1168
1148
#[ test_case( TEST_PTY ) ]
1169
1149
#[ tokio:: test]
1150
+ #[ traced_test]
1170
1151
async fn test_kill_process_group ( use_pty : bool ) {
1171
1152
let mut cmd = Command :: new ( "sh" ) ;
1172
1153
cmd. args ( [ "-c" , "while true; do sleep 0.2; done" ] ) ;
1173
1154
let mut child = Child :: spawn (
1174
1155
cmd,
1175
- ShutdownStyle :: Graceful ( Duration :: from_millis ( 100 ) ) ,
1156
+ // Bumping this to give ample time for the process to respond to the SIGINT to reduce
1157
+ // flakiness inherent with sending and receiving signals.
1158
+ ShutdownStyle :: Graceful ( Duration :: from_millis ( 500 ) ) ,
1176
1159
use_pty. then ( PtySize :: default) ,
1177
1160
)
1178
1161
. unwrap ( ) ;
0 commit comments