From 2a09883cc5320eb28611321c652215b039fb4cf0 Mon Sep 17 00:00:00 2001 From: Zo Bot Date: Fri, 19 Jun 2026 01:29:19 +0000 Subject: [PATCH] narrow Subprocess.__init__ Popen except to real Popen failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bare 'except:' wrapped subprocess.Popen() and a per-init pipe FD cleanup loop. The narrow set covers the actual failures of Popen(): OSError (FileNotFoundError when the executable isn't found, PermissionError when it isn't executable, OSError for other fork/exec failures), ValueError (embedded null byte in executable path), TypeError (unknown kwarg), and subprocess.SubprocessError (parent of all subprocess-raised errors added in Python 3.3; covers the cases where Popen detects an invalid argument combination internally). The bare except was also catching BaseException including KeyboardInterrupt and SystemExit — a Ctrl-C during the Popen call now propagates immediately to the asyncio task that owns the Subprocess instead of being swallowed and re-raised after the FD cleanup loop. --- tornado/process.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tornado/process.py b/tornado/process.py index 493481fd1..ab2b496f5 100644 --- a/tornado/process.py +++ b/tornado/process.py @@ -229,7 +229,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.stderr = PipeIOStream(err_r) try: self.proc = subprocess.Popen(*args, **kwargs) - except: + except (OSError, ValueError, TypeError, subprocess.SubprocessError): for fd in pipe_fds: os.close(fd) raise