@@ -9,33 +9,33 @@ use crate::commands::ExitStatus;
9
9
/// long as the command is the last thing that runs in this process; otherwise, we'd need to restore
10
10
/// the default signal handlers after the command completes.
11
11
pub ( crate ) async fn run_to_completion ( mut handle : Child ) -> anyhow:: Result < ExitStatus > {
12
- // On Unix, shells will send SIGINT to the active process group when a user presses `Ctrl-C`. In
13
- // general, this means that uv should ignore SIGINT, allowing the child process to cleanly exit
14
- // instead. If uv forwarded the SIGINT immediately, the child process would receive _two_ SIGINT
15
- // signals which has semantic meaning for some programs, i.e., slow exit on the first signal and
16
- // fast exit on the second. The exception to this is if a child process changes its process
17
- // group, in which case the shell will _not_ send SIGINT to the child process and uv must take
18
- // ownership of forwarding the signal.
12
+ // On Unix, the terminal driver will send SIGINT to the active process group when a user presses
13
+ // `Ctrl-C`. In general, this means that uv should ignore SIGINT, allowing the child process to
14
+ // cleanly exit instead. If uv forwarded the SIGINT immediately, the child process would receive
15
+ // _two_ SIGINT signals which has semantic meaning for some programs, i.e., slow exit on the
16
+ // first signal and fast exit on the second. The exception to this is if a child process changes
17
+ // its process group, in which case the terminal driver will _not_ send SIGINT to the child
18
+ // process and uv must take ownership of forwarding the signal.
19
19
//
20
- // Note this assumes an interactive shell . If a signal is sent directly to the uv parent process
21
- // (e.g., `kill -2 <pid>`), the process group is not involved and a signal is not sent to the
22
- // child by default. In this context, uv must forward the signal to the child. We work around
23
- // this by forwarding SIGINT if it is received more than once. We could attempt to infer if the
24
- // parent is a shell using TTY detection(?), but there hasn't been sufficient motivation to
25
- // explore alternatives yet.
20
+ // Note this assumes an interactive terminal . If a signal is sent directly to the uv parent
21
+ // process (e.g., `kill -2 <pid>`), the process group is not involved and a signal is not sent
22
+ // to the child by default. In this context, uv must forward the signal to the child. We work
23
+ // around this by forwarding SIGINT if it is received more than once. We could attempt to infer
24
+ // if the parent is a terminal using TTY detection(?), but there hasn't been sufficient
25
+ // motivation to explore alternatives yet.
26
26
//
27
- // Use of SIGTERM is also a bit complicated. If a shell receives a SIGTERM, it just waits for
27
+ // Use of SIGTERM is also a bit complicated. If a terminal receives a SIGTERM, it just waits for
28
28
// its children to exit — multiple SIGTERMs do not have any effect and the signals are not
29
29
// forwarded to the children. Consequently, the description for SIGINT above does not apply to
30
- // SIGTERM in shells . It is _possible_ to have a parent process that sends a SIGTERM to the
31
- // process group; for example, `tini` supports this via a `-g` option. In this case, it's
32
- // possible that uv will improperly send a second SIGTERM to the child process. However,
33
- // this seems preferable to not forwarding it in the first place. In the Docker case, if `uv`
34
- // is invoked directly (instead of via an init system), it's PID 1 which has a special-cased
35
- // default signal handler for SIGTERM by default. Generally, if a process receives a SIGTERM and
36
- // does not have a SIGTERM handler, it is terminated. However, if PID 1 receives a SIGTERM, it
37
- // is not terminated. In this context, it is essential for uv to forward the SIGTERM to the
38
- // child process or the process will not be killable.
30
+ // SIGTERM in the terminal driver . It is _possible_ to have a parent process that sends a
31
+ // SIGTERM to the process group; for example, `tini` supports this via a `-g` option. In this
32
+ // case, it's possible that uv will improperly send a second SIGTERM to the child process.
33
+ // However, this seems preferable to not forwarding it in the first place. In the Docker case,
34
+ // if `uv` is invoked directly (instead of via an init system), it's PID 1 which has a
35
+ // special-cased default signal handler for SIGTERM by default. Generally, if a process receives
36
+ // a SIGTERM and does not have a SIGTERM handler, it is terminated. However, if PID 1 receives a
37
+ // SIGTERM, it is not terminated. In this context, it is essential for uv to forward the SIGTERM
38
+ // to the child process or the process will not be killable.
39
39
#[ cfg( unix) ]
40
40
let status = {
41
41
use std:: ops:: Deref ;
@@ -162,8 +162,8 @@ pub(crate) async fn run_to_completion(mut handle: Child) -> anyhow::Result<ExitS
162
162
continue ;
163
163
}
164
164
165
- // The shell may still be forwarding these signals, give the child a moment to
166
- // handle that signal before hitting it with another one
165
+ // The terminal may still be forwarding these signals, give the child a moment
166
+ // to handle that signal before hitting it with another one
167
167
debug!( "Received SIGINT, forwarding to child at {child_pid} in 200ms" ) ;
168
168
tokio:: time:: sleep( std:: time:: Duration :: from_millis( 200 ) ) . await ;
169
169
let _ = signal:: kill( child_pid, signal:: Signal :: SIGINT ) ;
@@ -176,7 +176,7 @@ pub(crate) async fn run_to_completion(mut handle: Child) -> anyhow::Result<ExitS
176
176
} ;
177
177
178
178
// We unconditionally forward SIGTERM to the child process; unlike SIGINT, this
179
- // isn't usually handled by the shell and in cases like
179
+ // isn't usually handled by the terminal.
180
180
debug!( "Received SIGTERM, forwarding to child at {child_pid}" ) ;
181
181
let _ = signal:: kill( child_pid, signal:: Signal :: SIGTERM ) ;
182
182
}
0 commit comments