Skip to content

fix(run): drain redacted child output before exiting - #1292

Closed
dallenpyrah wants to merge 2 commits into
dmno-dev:mainfrom
dallenpyrah:fix-run-pipe-drain
Closed

dallenpyrah wants to merge 2 commits into
dmno-dev:mainfrom
dallenpyrah:fix-run-pipe-drain

Conversation

@dallenpyrah

@dallenpyrah dallenpyrah commented Nov 10, 2026 •

Copy link
Copy Markdown

run could exit before a descendant's inherited stdout/stderr pipes closed, dropping output that was still buffered by redaction. Drain both streams and actual redacted-write callbacks after retiring the exited child's signal forwarding, with a two-second cap and an incomplete-output diagnostic.

spawn(process.execPath, ['-e', `
  setTimeout(() => process.stdout.write('late output\\n'), 60)
`], { stdio: ['ignore', 1, 2] });
process.exit(0);

With the 28-byte regression payload: direct Node preserved 30/30 outputs; installed Varlock 1.24.0 lost 30/30. The added regression captures this case and a redacted last-write secret. Existing failure/forwarded-shutdown statuses stay intact; a signal arriving only after child exit cannot hide a drain failure.

Tested: 28 focused unit tests and 24 CLI smoke tests covering Node/Bun paused readers, closed stderr, redaction, SIGINT/SIGTERM, late signals and retained pipes; all 29 typecheck tasks passed.

@pullfrog pullfrog Bot 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.

Important

The parent-output drain needs fixes for Bun write completion and closed stderr pipes before merging.

Reviewed changes: Reviewed the output-draining helper, both command integrations, documentation, and regression tests.

  • Bounded drainage: run and proxy run wait for captured child streams and parent writes after retiring signal forwarding.
  • Timeout handling: Retained pipes produce an incomplete-output diagnostic while preserving existing failure or forwarded-shutdown statuses.
  • Regression coverage: Tests exercise delayed descendant output, redaction, retained pipes, and signals arriving after child exit.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog Bot 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.

✅ No new issues found.

Reviewed changes: Reviewed 54cad9c, the changes since the prior Pullfrog review.

  • Tracked actual writes: Replaced empty-write fences with per-source tracking of redacted output callbacks for both command integrations.
  • Preserved stderr behavior: Tolerated stderr EPIPE without replacing the child's exit status, while retaining other write errors and the drain deadline.
  • Added runtime regressions: Covered paused output readers and closed stderr consumers under Node and Bun, plus pending-write unit cases.

Validation passed: CLI build, varlock typecheck, 48 focused unit tests, and 21 output/signal smoke tests.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@theoephraim

Copy link
Copy Markdown
Member

Thanks for digging into this! Closing in favor of #1296, which fixes it in the shared exec helper (wait for the child's pipes to close after exit, capped at 2s) and also flushes varlock's own stdout before exiting, since gracefulExit's 1s flush cap was truncating output to slow readers. One behavior difference: when a backgrounded process still holds the pipe at the cap, we exit with the child's status rather than turning a successful run into an error, so the common sh -c 'server &' pattern keeps working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants