Summary
tool/shell.ts spawns child shell processes with detached: true on Linux, causing zombie processes to accumulate over multiple opencode run sessions.
Root Cause
In packages/opencode/src/tool/shell.ts:304:
detached: process.platform !== "win32",
On Linux this spawns shell processes via setsid() into their own process group/session. When these child processes exit before the parent calls waitpid(), and with no SIGCHLD handler anywhere in the codebase, they become <defunct> zombie processes.
Observed: 8 opencode run sessions accumulated 11 zombie processes. The only fix was kill -9 on the parent opencode processes.
Proposed Fix
Change line 304 to detached: false on all platforms:
Without setsid(), child processes remain in the parent's process group. Node.js can properly reap them when handle.exitCode resolves. Explicit process cleanup is already handled via handle.kill() in abort/timeout paths, so signal isolation via detached is unnecessary.
Also Benefits
Related
Summary
tool/shell.tsspawns child shell processes withdetached: trueon Linux, causing zombie processes to accumulate over multipleopencode runsessions.Root Cause
In
packages/opencode/src/tool/shell.ts:304:On Linux this spawns shell processes via
setsid()into their own process group/session. When these child processes exit before the parent callswaitpid(), and with noSIGCHLDhandler anywhere in the codebase, they become<defunct>zombie processes.Observed: 8
opencode runsessions accumulated 11 zombie processes. The only fix waskill -9on the parent opencode processes.Proposed Fix
Change line 304 to
detached: falseon all platforms:Without
setsid(), child processes remain in the parent's process group. Node.js can properly reap them whenhandle.exitCoderesolves. Explicit process cleanup is already handled viahandle.kill()in abort/timeout paths, so signal isolation viadetachedis unnecessary.Also Benefits
status=runningindefinitely after subprocess exits — pipe FD leak in spawn #29294 —detached: truecauses parent to retain write-end FDs of child stdout pipes, preventing EOF deliveryRelated
cross-spawn-spawner.ts