fix(update): drain uv/pip stderr - undrained pipe deadlocked windows desktop updates
Two consecutive Windows E2E runs hung inside dependency install until the job timeout: 31449642122 65 minutes in uv pip install .[all], 31453853006 43 minutes in the SQLite-repair uv sync (RUST_LOG=uv=debug made THAT run hang earlier and with more stderr - the tell). Root cause: scripts/desktop-update.ps1 redirects both child pipes but only pumps stdout while the child runs; stderr is ReadToEnd()'d after exit. uv and pip write progress to stderr. Once that pipe hits the ~64KB buffer, uv blocks on write, hermes update blocks on uv, the hand-off blocks on hermes update: deadlock. Slower stderr producers survive by finishing before the buffer fills, which is why the linux sandbox never sees this. Fix both sides of the class: - managed_uv.py candidate sync + main.py _run_install_with_heartbeat: merge stderr into stdout (the pipe that IS drained). This arm heals EXISTING installs, whose old hand-off script drives the NEW python after the git reset. - desktop-update.ps1: drain stderr concurrently via ReadToEndAsync so future bases never block regardless of what a child writes there. _run_logged_subprocess and _run_npm_install_deterministic already merge or capture both pipes; the two fixed sites were the only update- path spawns that redirect stderr without draining it live.
This commit is contained in:
@@ -780,6 +780,14 @@ def _stage_candidate_venv(
|
||||
# UV_NO_CONFIG drops it and uv 0.12+ refuses --locked.
|
||||
sync_env = dict(env)
|
||||
sync_env.pop("UV_NO_CONFIG", None)
|
||||
# stderr=STDOUT: uv writes progress to stderr. When the desktop
|
||||
# hand-off (scripts/desktop-update.ps1) runs `hermes update`, it only
|
||||
# drains the child's stdout while the child runs; a full stderr pipe
|
||||
# (~64KB) blocks uv forever. Run 31453853006 hung 43 minutes in this
|
||||
# exact call. Merging into stdout keeps the output streaming through
|
||||
# the pipe that IS drained. Old installed bases run their old copy of
|
||||
# the hand-off script, so the fix must live here, on the Python side
|
||||
# the update refreshes before dependencies are installed.
|
||||
synced = subprocess.run(
|
||||
[
|
||||
uv_bin,
|
||||
@@ -792,6 +800,7 @@ def _stage_candidate_venv(
|
||||
],
|
||||
cwd=project_root,
|
||||
env=sync_env,
|
||||
stderr=subprocess.STDOUT,
|
||||
check=False,
|
||||
)
|
||||
if synced.returncode != 0:
|
||||
|
||||
Reference in New Issue
Block a user