Skip to content

fix(cli): await trailing progress-log writes before settling download - #1122

Merged
EhabY merged 1 commit into
mainfrom
fix/cli-download-trailing-progress-write-race
Sep 23, 2026
Merged

EhabY merged 1 commit into
mainfrom
fix/cli-download-trailing-progress-write-race

Conversation

@EhabY

@EhabY EhabY commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Fixes #1120

Root cause

CliManager.download() settled its promise on a progressWrite captured by value at the moment the read stream closed. A chunk write still in flight at that point was never awaited, so clearProgress() could delete binary.progress.log first and the trailing write would recreate it, leaving the file behind permanently. That is why the concurrent test failed only on the progress-log line and no vi.waitFor timeout could fix it.

Fix

Two changes in download():

  • Progress-log writes are chained onto the previous one, so awaiting the final progressWrite awaits every write, not just the last.
  • All three settle paths (success, read error, write error) settle only after the write stream emits close, which fs guarantees fires after every pending write callback.

Cleanup can no longer race a trailing write, on any scheduler.

Tests

  • New regression test holds fs write callbacks until close(), like a real stream on a loaded runner. Fails on unfixed code, passes with the fix.
  • withStreamError("write") now emits close after error, matching real fs with autoClose: true.
  • The concurrent test's vi.waitFor polling is removed; cleanup is complete when the download promises settle.

🤖 Generated by Coder Agents

@EhabY
EhabY force-pushed the fix/cli-download-trailing-progress-write-race branch from a5fcadf to a051b0b Compare September 21, 2026 14:12
@EhabY
EhabY requested a review from aqandrew September 21, 2026 15:28

@aqandrew aqandrew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate you DRYing up the settle paths in cliManager.ts too 🙂

Comment thread test/unit/core/cliManagerHarness.ts Outdated
The download promise settled on a progressWrite captured by value, so a
chunk write still in flight could recreate the progress log after cleanup
cleared it, leaving a stale binary.progress.log behind. Chain each
progress-log write onto the previous one and settle only after the write
stream closes, so every write is awaited before cleanup runs.
@EhabY
EhabY force-pushed the fix/cli-download-trailing-progress-write-race branch from a051b0b to 1b498fe Compare September 23, 2026 09:39
@EhabY
EhabY merged commit 6c4976c into main Sep 23, 2026
13 checks passed
@EhabY
EhabY deleted the fix/cli-download-trailing-progress-write-race branch September 23, 2026 09:43
@EhabY EhabY mentioned this pull request Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky test: concurrent CLI redownload times out waiting for the progress log to go away

2 participants