Repository navigation
runner: exit after the result line drains (#63) - #67
gabe-bots[bot] wants to merge 2 commits into
Conversation
|
@greptile review |
[Medium impact] Changes how the runner process exits after sending results. Stop pending program callbacks during the final write before merging. Findings
Fix with agent prompt### Issue 1
runtime/runner.mjs:49
Waiting for stdout leaves pending program callbacks active. For example, `sleep(0).then(() => { while (true) {} }); return 'x'.repeat(1000000)` can start its loop while the result is still draining. The loop prevents the remaining writes and exit callback from running. The host then waits until the CPU limit kills the runner and receives an incomplete result.
Stop pending program callbacks when `finished` becomes true, while allowing stdout to drain.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
|
| finished = true | ||
| emit(msg) | ||
| process.exit(0) | ||
| process.stdout.write(lineOf(msg), () => process.exit(0)) |
There was a problem hiding this comment.
Background work blocks the result
Waiting for stdout leaves pending program callbacks active. For example, sleep(0).then(() => { while (true) {} }); return 'x'.repeat(1000000) can start its loop while the result is still draining. The loop prevents the remaining writes and exit callback from running. The host then waits until the CPU limit kills the runner and receives an incomplete result.
Stop pending program callbacks when finished becomes true, while allowing stdout to drain.
Prompt To Fix With AI
This is a comment left during a code review.
Path: runtime/runner.mjs
Line: 49
Comment:
**Background work blocks the result**
Waiting for stdout leaves pending program callbacks active. For example, `sleep(0).then(() => { while (true) {} }); return 'x'.repeat(1000000)` can start its loop while the result is still draining. The loop prevents the remaining writes and exit callback from running. The host then waits until the CPU limit kills the runner and receives an incomplete result.
Stop pending program callbacks when `finished` becomes true, while allowing stdout to drain.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Intent
A large
run_coderesult reaches the host as one whole line. The host then clips that value and namesrecall.%%{init: {'theme': 'neutral'}}%% flowchart TD A[Program returns a large value] --> B[finish writes the result line] B --> C[Write callback waits for the pipe] C --> D[process.exit after the line is out] D --> E[takeMessages reads one done line] E --> F[Host clips the value and names recall]Drift
None.
Decisions
fs.writeSynccan throwEAGAINon a pipe.7f9f09brestores the old exit.Evidence
Before (
EXPECT_NETWORK_BLOCK=1 node tests/runner.integration.mjs, then the host-text script):After:
Reading map
tests/runner.integration.mjs, the twomake it failcases..claude-plugin/plugin.jsonversion0.12.14.Stack
Step 1 of 2. The base is
main. There is no previous step. The next branch isquality/64-pretty-cut.Part of #63
Story
A large
run_coderesult reaches the host whole, and the host keeps each result that it cuts forrecall.quality/63-runner-drainawait recall(n), andrecall(n)gives back 800 itemsquality/64-pretty-cut