You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[BUG] Queued SessionPrompt.loop() callers can hang forever on cancel/dispose #14565
When a session is already busy, SessionPrompt.loop() returns a Promise and pushes its { resolve, reject } handlers into state()[sessionID].callbacks. If the session is cancelled (or the instance is disposed) while callbacks are queued, we abort/delete state but never reject those queued promises. Concurrent callers can wait forever.
This should be resolved by the upstream Effect/Runner migration.
c5442d418d — refactor(session): effectify SessionPrompt service (#19483) (Mar 30) introduces a Runner state machine that replaces the old SessionPrompt.loop() queueing. The Runner uses SynchronizedRef-based atomic state transitions with four states: Idle, Running, Shell, ShellThenRun.
Key changes relevant to this issue:
Concurrent loop() callers coalesce — Runner.ensureRunning returns the same Deferred to all callers when a run is already in progress. No more queueing or hanging.
Cancel interrupts the fiber — Runner.cancel does Fiber.interrupt, which propagates through Deferred.await in Permission/Question services. Pending waits are interrupted, not left dangling.
Runner.Cancelled error — interrupted callers get a typed Cancelled error instead of hanging indefinitely.
Scope finalization — addFinalizer on Permission/Question state rejects all pending deferreds on scope close.
We had a PR (#20102) targeting this with a different approach (generation-guarded cancel, precancelled map, explicit rejectSession()), but it was obsoleted by this architectural change before it could be merged. Closed it with details in the PR comment.
Activity
ESRE-dev commentedon Apr 1, 2026
This should be resolved by the upstream Effect/Runner migration.
c5442d418d—refactor(session): effectify SessionPrompt service (#19483)(Mar 30) introduces aRunnerstate machine that replaces the oldSessionPrompt.loop()queueing. TheRunnerusesSynchronizedRef-based atomic state transitions with four states:Idle,Running,Shell,ShellThenRun.Key changes relevant to this issue:
loop()callers coalesce —Runner.ensureRunningreturns the sameDeferredto all callers when a run is already in progress. No more queueing or hanging.Runner.canceldoesFiber.interrupt, which propagates throughDeferred.awaitin Permission/Question services. Pending waits are interrupted, not left dangling.Runner.Cancellederror — interrupted callers get a typedCancellederror instead of hanging indefinitely.addFinalizeron Permission/Question state rejects all pending deferreds on scope close.We had a PR (#20102) targeting this with a different approach (generation-guarded cancel,
precancelledmap, explicitrejectSession()), but it was obsoleted by this architectural change before it could be merged. Closed it with details in the PR comment.cc #20095 (related issue, now closed)