fix: keep stderr after the report it closes

verify.py --emulator fbneo --strict > log 2>&1 put the ERROR verdict on
the first line of the log: redirected, stdout is block-buffered and
stderr is not, and run_cli flushed stdout only after main returned.
run_cli now sets stdout to line buffering, so every tool it runs keeps
the two streams in the order they were written.
This commit is contained in:
Abdessamad Derraz committed 2026-11-06 15:06:26 +01:00
1 parent 3eade14d4f
commit 1fe37d16ac
2 files changed
+32

No files matched your search

+7
View File
@@ -3676,6 +3676,13 @@ def run_cli(main: Callable[[], int | None]) -> None:
for name in ("SIGTERM", "SIGHUP"):
if hasattr(signal, name):
signal.signal(getattr(signal, name), _exit_on_signal)
# Redirected, stdout is block-buffered and stderr is not: the --strict
# verdict landed on the first line of the log, before the report it
# closes. Line buffering keeps the two in the order they were written.
# A stream a caller swapped in (a test's StringIO) has nothing to set.
reconfigure = getattr(sys.stdout, "reconfigure", None)
if reconfigure is not None:
reconfigure(line_buffering=True)
try:
code = main()
sys.stdout.flush()
+25
View File
@@ -147,6 +147,31 @@ class ADamagedProfileNamesItself(unittest.TestCase):
self.assertFalse(issubclass(common.SourceUnreadable, FileNotFoundError))
class TheVerdictClosesARedirectedReport(unittest.TestCase):
"""`verify.py --emulator fbneo --strict > log 2>&1` put the --strict
ERROR on the first line of the log: stdout redirected is block-buffered,
stderr is not, and the report it closes came after."""
def test_stderr_stays_after_what_stdout_wrote_first(self):
program = (
"import sys\n"
"sys.path.insert(0, 'scripts')\n"
"from common import run_cli\n"
"def main():\n"
" print('report')\n"
" print('ERROR: verdict', file=sys.stderr)\n"
" return 1\n"
"run_cli(main)\n"
)
env = {k: v for k, v in os.environ.items() if k != "PYTHONUNBUFFERED"}
proc = subprocess.run(
[sys.executable, "-c", program], cwd=REPO_ROOT, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, text=True, timeout=60, check=False, env=env,
)
self.assertEqual(proc.returncode, 1)
self.assertEqual(proc.stdout.splitlines(), ["report", "ERROR: verdict"])
class AMistypedTargetAcrossAllPlatforms(unittest.TestCase):
"""`verify --all --target swich` ended on "no platform has it" after 17
INFO lines, two of which held the suggestion."""