Skip to content

fix(bg-shell): prevent stale context crash after session replacement - #120

Merged
itayinbarr merged 2 commits into
itayinbarr:mainfrom
ktutumi:codex/fix/119-bg-shell-stale-ctx
Aug 29, 2026
Merged

itayinbarr merged 2 commits into
itayinbarr:mainfrom
ktutumi:codex/fix/119-bg-shell-stale-ctx

Conversation

@ktutumi

@ktutumi ktutumi commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Ignore late process output and completion side effects from jobs removed during session reaping.
  • Clear the cached UI context and contain stale hasUI access during session replacement.
  • Preserve exit-state tracking so graceful termination does not trigger a delayed SIGKILL.
  • Add real-process regression coverage for stale contexts, replacement-session UI and wake isolation, late output, and force-kill cancellation.

Root cause

reapAll() sends SIGTERM asynchronously and clears the job map before child-process data and close events necessarily finish. Those late events could access the stale cached UI context or wake and repaint the replacement session.

Testing

  • npm test — 677 passed, 14 skipped
  • npm run typecheck
  • Confirmed the late-output regression test fails before the stream guard and passes after it.

Closes #119

Ignore completion side effects from reaped jobs while recording their exit state so delayed force-kill escalation is cancelled. Clear cached UI contexts during reaping and contain stale UI access.

Add regression coverage for stale contexts, replacement-session UI updates, wake delivery, and unnecessary SIGKILL escalation.

Fixes itayinbarr#119
Prevent stdout and stderr events that arrive after session reaping from scheduling or delivering wakes to the replacement session. Add a real-process regression test using a SIGTERM trap.

Refs: itayinbarr#119

@itayinbarr itayinbarr left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved and merging. Thank you for filing the issue and the fix together, with a harness that reproduces a timing-dependent crash deterministically. That is the hard part of this bug.

Your root cause is right, and I want to record the part that is easy to miss on review: the one-line move of hasUI into the try is the crash fix, but on its own it would have left the worse half of the bug in place. A reaped job's late data and close events would still repaint and wake the replacement session, so /new would have silently leaked the old session's job output into the new one instead of crashing. The jobs.has(job.id) guards are what actually make reaping mean something.

The ordering inside finish() is the detail I checked hardest, because it is the one that would have bitten later:

job.exited = true;          // before the map check
job.exitCode = code;
job.endedAt = Date.now();
if (!jobs.has(job.id)) return;

Setting exited ahead of the early return keeps scheduleForceKill's hasExited() gate honest for a job that reapAll already removed. Returning first would have re-introduced #102's orphan-SIGKILL problem from the other direction, and your fourth test pins exactly that. Good catch.

Verified locally: full suite 677 passed, typecheck clean, branch not behind main. CI was sitting in action_required because you are a first-time contributor here; I have approved the workflow run.

I am folding this into a wider pass in the same release. This is the third instance of the same shape (#108 in the context watchdog, now this), and SubCoderTracker holds a ctx across async sub-coder updates the same way, so I am adding a shared guard rather than waiting for the fourth report.

@itayinbarr
itayinbarr merged commit e678961 into itayinbarr:main Aug 29, 2026
1 check passed
cristiannegru pushed a commit to cristiannegru/little-coder that referenced this pull request Sep 17, 2026
- assets/banner.svg: aider polyglot 78.7% (35B-A3B), TB2.0 rank itayinbarr#120,
  drop the model line, accurate annotations, re-flowed prompt lines.
- site/: static one-pager (HTML/CSS/vanilla JS) deployed to GitHub Pages.
  Content driven by the paper + the repo's real behavior: npm install,
  llama.cpp serving, the actual little-coder tool-use flow, Apache-2.0.
  Community section features real answered issues; stars/issues/version
  fetch live from the GitHub API with baked-in fallbacks.
- .github/workflows/pages.yml: Actions deploy of site/ to Pages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bg-shell: /new can crash when a reaped job emits close on a stale context

2 participants