fix(opencode): defer config reload until sessions are idle - #42622
Open
matjam wants to merge 1 commit into
Open
Conversation
SIGUSR2 asks the TUI worker to reload config, which disposes every instance. Instance disposal cancels the session runners that instance owns, so a signal that lands while the model is streaming interrupts the run. Desktop environments send this signal on theme changes - Omarchy's omarchy-theme-set runs `killall -SIGUSR2 opencode` - so switching themes mid-run aborts the in-flight request. Theme refresh does not depend on the worker reload: the TUI re-detects the terminal palette and re-scans theme files from its own SIGUSR2 handler. Wait for every instance to have no busy session before invalidating config and disposing, and coalesce signals that arrive while waiting, so the reload is deferred rather than dropped.
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.
Issue for this PR
Closes #42621
Type of change
What does this PR do?
SIGUSR2 makes the TUI worker reload config, and that reload disposes every instance. Instance disposal cancels the session runners the instance owns, so a signal that lands mid-run kills whatever is in flight. Desktop environments send SIGUSR2 on theme changes (Omarchy runs
killall -SIGUSR2 opencode), so switching themes while opencode is working aborts the request.The reload now waits until no instance has a busy session before invalidating config and disposing, so the reload is deferred rather than dropped. Signals that arrive while waiting join the pending reload instead of stacking.
Themes still update immediately — that path never went through the worker. The TUI re-detects the terminal palette and re-scans theme files from its own SIGUSR2 handler.
InstanceStore.list()is new; the wait needs it to checkSessionStatusper instance.How did you verify your code works?
Manually, before and after, using a shell command so no model call is involved:
bun dev, then!sleep 45, thenkill -SIGUSR2 <tui pid>from another terminal.disposing all instances~5ms after the signal.disposing all instancesappears once the session goes idle — so the config reload still happens, just later.Tests:
test/server/global-lifecycle.test.ts(new):awaitSessionsIdlereturns while idle, and blocks until a busy session goes idle. Checked that it fails if the busy predicate is broken.test/project/instance.test.ts: coverage forInstanceStore.list().bun typecheckclean inpackages/opencode;bun test test/server/httpapi-global.test.ts test/project/passes.Checklist