@@ -11,6 +11,8 @@ use futures::StreamExt;
11
11
use itertools:: Itertools ;
12
12
use owo_colors:: OwoColorize ;
13
13
use tokio:: process:: Command ;
14
+ use tokio:: select;
15
+ use tokio:: signal:: unix:: { signal, SignalKind } ;
14
16
use tracing:: { debug, warn} ;
15
17
use url:: Url ;
16
18
use uv_cache:: Cache ;
@@ -994,9 +996,28 @@ pub(crate) async fn run(
994
996
// Ignore signals in the parent process, deferring them to the child. This is safe as long as
995
997
// the command is the last thing that runs in this process; otherwise, we'd need to restore the
996
998
// signal handlers after the command completes.
997
- let _handler = tokio:: spawn ( async { while tokio:: signal:: ctrl_c ( ) . await . is_ok ( ) { } } ) ;
999
+ let mut term_signal = signal ( SignalKind :: terminate ( ) ) ?;
1000
+ let mut int_signal = signal ( SignalKind :: interrupt ( ) ) ?;
998
1001
999
- let status = handle. wait ( ) . await . context ( "Child process disappeared" ) ?;
1002
+ let status = select ! {
1003
+ status = handle. wait( ) => status,
1004
+
1005
+ // `SIGTERM`
1006
+ _ = term_signal. recv( ) => {
1007
+ handle. kill( ) . await ?;
1008
+ handle. wait( ) . await . context( "Child process disappeared" ) ?;
1009
+ return Ok ( ExitStatus :: Failure ) ;
1010
+ }
1011
+
1012
+ // `SIGINT`
1013
+ _ = int_signal. recv( ) => {
1014
+ handle. kill( ) . await ?;
1015
+ handle. wait( ) . await . context( "Child process disappeared" ) ?;
1016
+ return Ok ( ExitStatus :: Failure ) ;
1017
+ }
1018
+ } ;
1019
+
1020
+ let status = status. context ( "Child process disappeared" ) ?;
1000
1021
1001
1022
// Exit based on the result of the command
1002
1023
if let Some ( code) = status. code ( ) {
0 commit comments