Subagent kernel wedged in C-level code is abandoned by headless busy-cancel and spins at 100% CPU forever #2026
cj848
started this conversation in
Bug reports
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Description
A subagent (headless
rlmchild) gets its own Python kernel process spawned by the parent agent process. If that kernel gets wedged inside a single C-level call — observed with catastrophic regex backtracking, where the interpreter never returns to the eval loop and holds the GIL — then:interruptframe, andso neither in-band interrupt mechanism can reach it. After the busy-reuse window expires,
KernelBusyAfterInterruptErroris thrown. In a headless context there is no UI, sochooseBusyKernelAction()returns"cancel": the tool call fails, but the kernel manager is never disposed (noshutdown(), no kill).The kernel process then spins at one full CPU core indefinitely while the parent agent keeps working on replacement kernels. Observed a wedged subagent kernel pinned at ~100% CPU for ~50 minutes until it was killed manually; nothing reclaims it earlier because the parent process stays alive, and the orphan-process reaper only covers
bash()grandchildren, not the kernel process itself.A milder variant of the same leak: when a subagent session ends normally, its kernel process also survives (idle, memory-only cost) as long as the parent process lives.
Steps to reproduce
Start an interactive
prime-agentsession (npm install).Spawn a headless subagent so its kernel starts, e.g.
handle = await rlm('sub-task', name='wedge-test').In that subagent, run an ipython cell that wedges inside a C call, for example:
Let the subagent's turn abort / time out, or delete the subagent while the cell is still running.
The subagent fails and the parent continues on other kernels, but the subagent's kernel process (
kernel-venv/bin/python -m rlm.repl) stays alive at ~100% CPU forever.psconfirms it is pinned; killing it manually is harmless to the parent (a fresh kernel is spawned on next use).Expected behavior
Actual behavior
"cancel"and abandons the manager (suspected area:chooseBusyKernelActioninpackages/coding-agent/src/core/tools/ipython.ts).active: truerecord for the wedged kernel — no inactive record — meaning the teardown/cleanup path never ran for it.Workaround
An external watchdog that kills
rlm.replprocesses sustaining ~100% CPU past a threshold (e.g. ≥90% with ≥300s cumulative CPU time).Environment
chooseBusyKernelActionis unchanged on currentmain)All reactions