fix(infra): handle detached respawn child errors#101502
Closed
LiLan0125 wants to merge 1 commit into
Closed
Conversation
Member
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
errorlistener to the detached gateway update respawn child before callingunref().unref()and can consume an async spawn error.Change Type
Scope
Real behavior proof
Behavior addressed: Detached gateway update respawn no longer leaves the returned
ChildProcesswithout anerrorlistener, so asynchronous spawn failures do not become unhandled child-process errors.Environment tested: Linux source checkout on branch
fix/101458-process-respawn-error, Node running TypeScript sources throughnode --import tsx, plus the targeted Vitest shard throughnode scripts/run-vitest.mjs.Steps run after the patch: Called the actual
respawnGatewayProcessForUpdate()production function fromsrc/infra/process-respawn.ts, forced a detached spawn with a missingprocess.execPath, waited for the childerrorevent, and confirmed the parent process stayed alive. Also ran the targeted process respawn test file.Evidence after fix: Production function proof:
Output:
{ "mode": "spawned", "pid": null, "hasChild": true, "childError": "ENOENT:true", "processStillRunning": true }Targeted test proof:
Observed result: The production respawn path returned a spawned child, the missing executable emitted
ENOENT, and the parent process stayed alive long enough to printprocessStillRunning: true. The targeted test shard also passed, including the assertion thatchild.on("error", ...)is registered beforechild.unref()and that invoking the captured error listener does not throw.Not tested: Full live OpenClaw package update respawn with a real gateway process was not run; the proof exercises the same production respawn function and Node child-process error path with a deliberately missing executable.
Root Cause
spawnDetachedGatewayProcess()spawned and unref'd the detached update child without attaching anerrorlistener.errorevent without a listener as an unhandled exception, so asynchronous spawn failures can terminate the parent process.Regression Test Plan
src/infra/process-respawn.test.tsnow covers the detached update respawn path and asserts that theerrorlistener is attached beforeunref().Verification
node --import tsx --no-warnings -e '...'production-function proof passed and printedprocessStillRunning: true.node scripts/run-vitest.mjs src/infra/process-respawn.test.tspassed.git diff --checkpassed.Impact Assessment
respawnGatewayProcessForUpdate()keeps returning the spawned child and pid; detached process behavior is unchanged except async child errors are consumed best-effort.spawn()throws still returnmode: "failed"; asynchronousChildProcesserrors after spawn are now handled.User-visible / Behavior Changes
Gateway update respawn is more resilient when a detached child emits an asynchronous spawn error such as ENOENT or ENOMEM.
Security Impact
Closes #101458