@@ -9,33 +9,33 @@ use crate::commands::ExitStatus;
99/// long as the command is the last thing that runs in this process; otherwise, we'd need to restore
1010/// the default signal handlers after the command completes.
1111pub ( 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.
1919 //
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.
2626 //
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
2828 // its children to exit — multiple SIGTERMs do not have any effect and the signals are not
2929 // 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.
3939 #[ cfg( unix) ]
4040 let status = {
4141 use std:: ops:: Deref ;
@@ -162,8 +162,8 @@ pub(crate) async fn run_to_completion(mut handle: Child) -> anyhow::Result<ExitS
162162 continue ;
163163 }
164164
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
167167 debug!( "Received SIGINT, forwarding to child at {child_pid} in 200ms" ) ;
168168 tokio:: time:: sleep( std:: time:: Duration :: from_millis( 200 ) ) . await ;
169169 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
176176 } ;
177177
178178 // 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.
180180 debug!( "Received SIGTERM, forwarding to child at {child_pid}" ) ;
181181 let _ = signal:: kill( child_pid, signal:: Signal :: SIGTERM ) ;
182182 }
0 commit comments