From 3e6acf2778b533aedb2a1f6f6e3a3159e0b8c86d Mon Sep 17 00:00:00 2001 From: Gavin Mak Date: Wed, 13 Aug 2025 00:07:29 -0700 Subject: progress: Fix race condition causing fileno crash A race condition occurs when sync redirects sys.stderr to capture worker output, while a background progress thread simultaneously calls fileno() on it. This causes an io.UnsupportedOperation error. Fix by caching the original sys.stderr for all progress bar IO. Change-Id: Idb1f45d707596d31238a19fd373cac3bf669c405 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/498121 Tested-by: Gavin Mak Reviewed-by: Scott Lee --- progress.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'progress.py') diff --git a/progress.py b/progress.py index 30ec8c3b..9a91dcd6 100644 --- a/progress.py +++ b/progress.py @@ -25,7 +25,10 @@ except ImportError: from repo_trace import IsTraceToStderr -_TTY = sys.stderr.isatty() +# Capture the original stderr stream. We use this exclusively for progress +# updates to ensure we talk to the terminal even if stderr is redirected. +_STDERR = sys.stderr +_TTY = _STDERR.isatty() # This will erase all content in the current line (wherever the cursor is). # It does not move the cursor, so this is usually followed by \r to move to @@ -133,11 +136,11 @@ class Progress: def _write(self, s): s = "\r" + s if self._elide: - col = os.get_terminal_size(sys.stderr.fileno()).columns + col = os.get_terminal_size(_STDERR.fileno()).columns if len(s) > col: s = s[: col - 1] + ".." - sys.stderr.write(s) - sys.stderr.flush() + _STDERR.write(s) + _STDERR.flush() def start(self, name): self._active += 1 @@ -211,9 +214,9 @@ class Progress: # Erase the current line, print the message with a newline, # and then immediately redraw the progress bar on the new line. - sys.stderr.write("\r" + CSI_ERASE_LINE) - sys.stderr.write(msg + "\n") - sys.stderr.flush() + _STDERR.write("\r" + CSI_ERASE_LINE) + _STDERR.write(msg + "\n") + _STDERR.flush() self.update(inc=0) def end(self): -- cgit v1.2.3-54-g00ecf