From ae902250bd65cb530adf63615df0f8e877e0b029 Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Wed, 4 Mar 2026 08:45:38 +0100 Subject: [PATCH] jw/pkg/lib/util.run_cmd(): Chunked read_stream() jw-pkg distro dup got hung in a chroot environment. strace shows that write(2) into a pipe is the hanging syscall, with the write buffer hinting at zypper dup output. I strongly suspect that run_cmd() tries to write stdout into the pipe which read_stream() fails to empty. So, make read_stream() more resilient by using read(4096) instead of readline(), which I suspect to be prone to hang on overlong lines. Signed-off-by: Jan Lindemann --- src/python/jw/pkg/lib/util.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/python/jw/pkg/lib/util.py b/src/python/jw/pkg/lib/util.py index 119ece1b..6d97fdb1 100644 --- a/src/python/jw/pkg/lib/util.py +++ b/src/python/jw/pkg/lib/util.py @@ -172,13 +172,20 @@ async def run_cmd( stderr_log_enc = output_encoding async def read_stream(stream, prio, collector: list[bytes], log_enc: str): + buf = b"" while True: - line = await stream.readline() - if not line: + chunk = await stream.read(4096) + if not chunk: break - collector.append(line) + collector.append(chunk) if verbose: - __log(prio, line.decode(log_enc, errors="replace").rstrip("\n")) + buf += chunk + while b"\n" in buf: + line, buf = buf.split(b"\n", 1) + __log(prio, line.decode(log_enc, errors="replace")) + if verbose and buf: + # flush trailing partial line (no newline) + __log(prio, buf.decode(log_enc, errors="replace")) tasks = [ asyncio.create_task(