fix: cancel widget auto-clear timers on session_shutdown (stale ctx crash) - #121
Open
JohannesBertens wants to merge 1 commit into
Open
JohannesBertens wants to merge 1 commit into
JohannesBertens wants to merge 1 commit into
Conversation
pi invalidates the extension ctx on session replacement (newSession, fork, switchSession, reload) and process exit. The widget auto-clear setTimeout callbacks captured ctx and read `ctx.hasUI`, which throws from assertActive() on a stale ctx; inside a bare timer callback that throw became an uncaughtException that killed the whole pi process. Track pending widget clears in a module-level Set, cancel them all in session_shutdown (and in _resetState for test isolation), and make the callback itself stale-ctx-safe: hasUI is captured while the ctx is guaranteed live and setWidget is wrapped in try/catch as a second line of defense. Fixes weauratech#120
This branch has not been deployed
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.
Fixes #120
Problem
pi exits with an
uncaughtExceptionwhen a transient widget's auto-clear timer fires after the session has been replaced:All three widget auto-clear timers (
memctx-tool-failure,memctx-learned,memctx-learn) capturectxand dereference it up to 30s later:pi invalidates the extension ctx on session replacement (newSession, fork, switchSession, reload) and process exit — every property access then throws from
assertActive(). Thectx.hasUI &&guard cannot help because the getter itself is the crash site, and since the throw happens in a bare timer callback (no surrounding event dispatch or try/catch), it surfaces as a process-leveluncaughtExceptionand kills pi.Repro: queue a memory candidate at end of turn (the
memctx-learnwidget appears), start a new session within 30s, wait for the timer.Fix
Setand all cancelled in the existingsession_shutdownhandler. pi emitssession_shutdownfor the old extension instance on every replacement path and before exit, so a pending clear can never outlive its session. This also stops the 20–30s timers from delaying process exit.hasUIis captured while the ctx is guaranteed live (headless-p/JSON sessions still never touchui), andsetWidgetis wrapped in try/catch in case a clear ever races the shutdown event._resetStatealso cancels pending clears for test isolation.Scoped deliberately to the timers: the other deferred
ctxtouches in theagent_endcuration IIFE already sit inside itstry/catch, so they cannot crash the process.Tests
New
widget auto-clear timerssection intest/unit.test.ts:setWidgetafter the delaysession_shutdowncancels pending widget clears (driven through the registered handler)uncaughtExceptionexit (ctx whosehasUI/setWidgetthrow like pi'sassertActive)hasUI === false) never touchessetWidgetnpm run typecheckandnpm run lintpass;bun test test/unit.test.ts→ 118 pass / 0 fail (4 new).Checklist
[Unreleased]Related: #114 (same stale-ctx family, headless
/memctx-init).