From f5305653238378376cd33f1a00d6b9eb511bef36 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 11 Jun 2025 08:28:34 -0500 Subject: [PATCH] Use TTY detection to determine if SIGINT forwarding is enabled (#13925) Use TTY detection to determine when we should forward SIGINT instead of counting signals, which can lead to various problems where multiple SIGINTs are sent to a child after the first signal. Counting does not make sense in interactive situations that do not exit on interrupt, e.g., the Python REPL. Closes https://github.com/astral-sh/uv/issues/13919 Closes https://github.com/astral-sh/uv/issues/12108 --- crates/uv/src/commands/run.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/crates/uv/src/commands/run.rs b/crates/uv/src/commands/run.rs index 8b4ceaf2d..6a8033fff 100644 --- a/crates/uv/src/commands/run.rs +++ b/crates/uv/src/commands/run.rs @@ -17,12 +17,11 @@ pub(crate) async fn run_to_completion(mut handle: Child) -> anyhow::Result`), the process group is not involved and a signal is not sent - // to the child by default. In this context, uv must forward the signal to the child. We work - // around this by forwarding SIGINT if it is received more than once. We could attempt to infer - // if the parent is a terminal using TTY detection(?), but there hasn't been sufficient - // motivation to explore alternatives yet. + // Note the above only applies in an interactive terminal. If a signal is sent directly to the + // uv parent process (e.g., `kill -2 `), the process group is not involved and a signal is + // not sent to the child by default. In this context, uv must forward the signal to the child. + // uv checks if stdin is a TTY as a heuristic to determine if uv is running in an interactive + // terminal. When not in an interactive terminal, uv will forward SIGINT to the child. // // Use of SIGTERM is also a bit complicated. If a terminal receives a SIGTERM, it just waits for // its children to exit — multiple SIGTERMs do not have any effect and the signals are not @@ -38,6 +37,7 @@ pub(crate) async fn run_to_completion(mut handle: Child) -> anyhow::Result anyhow::Result anyhow::Result anyhow::Result