Skip to content

Commit 3e6acf2

Browse files
committed
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 <[email protected]> Reviewed-by: Scott Lee <[email protected]>
1 parent a6e1a59 commit 3e6acf2

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

progress.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
from repo_trace import IsTraceToStderr
2626

2727

28-
_TTY = sys.stderr.isatty()
28+
# Capture the original stderr stream. We use this exclusively for progress
29+
# updates to ensure we talk to the terminal even if stderr is redirected.
30+
_STDERR = sys.stderr
31+
_TTY = _STDERR.isatty()
2932

3033
# This will erase all content in the current line (wherever the cursor is).
3134
# It does not move the cursor, so this is usually followed by \r to move to
@@ -133,11 +136,11 @@ def _update_loop(self):
133136
def _write(self, s):
134137
s = "\r" + s
135138
if self._elide:
136-
col = os.get_terminal_size(sys.stderr.fileno()).columns
139+
col = os.get_terminal_size(_STDERR.fileno()).columns
137140
if len(s) > col:
138141
s = s[: col - 1] + ".."
139-
sys.stderr.write(s)
140-
sys.stderr.flush()
142+
_STDERR.write(s)
143+
_STDERR.flush()
141144

142145
def start(self, name):
143146
self._active += 1
@@ -211,9 +214,9 @@ def display_message(self, msg):
211214

212215
# Erase the current line, print the message with a newline,
213216
# and then immediately redraw the progress bar on the new line.
214-
sys.stderr.write("\r" + CSI_ERASE_LINE)
215-
sys.stderr.write(msg + "\n")
216-
sys.stderr.flush()
217+
_STDERR.write("\r" + CSI_ERASE_LINE)
218+
_STDERR.write(msg + "\n")
219+
_STDERR.flush()
217220
self.update(inc=0)
218221

219222
def end(self):

0 commit comments

Comments
 (0)