Repository navigation
ADFA-5422: Load each color scheme once, under a lock - #2129
Open
Daniel-ADFA wants to merge 1 commit into
Open
Daniel-ADFA wants to merge 1 commit into
Daniel-ADFA wants to merge 1 commit into
Conversation
Opening a project restores its editor tabs together, and each editor reads the color scheme on its own IO coroutine. IDEColorSchemeProvider caches the scheme in an unsynchronized lazy getter, so two editors can both call IDEColorScheme.load() on the same instance at once. Both parse into the same MutableIntIntMap and ++colorId counter, which are not thread-safe. parseColorValue() caught any failure from putColor() and returned the raw ARGB color as the color id, so a corrupted write became an out-of-range id that StyleDef.makeStyle() passed to TextStyle.makeStyle(), which throws "color id must be positive and bit count is less than 19" (GlitchTip CODEONTHEGO-K, 42 fatal events, still on C-r-1006). Other interleavings leave the map's probe loop spinning forever. load() is now synchronized and returns once the scheme is loaded, so the second editor waits for the first and reuses its result. Nothing reloads an instance on purpose: load() is only reached through loadColorScheme() while the provider's cached scheme is still null. putColor() failures now propagate to IDEColorSchemeProvider.loadColorScheme(), which logs them and falls back to the default scheme, instead of surfacing later as a crash.
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
Contributor
itsaky-adfa
approved these changes
Oct 12, 2026
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.
ADFA-5422
Fixes the fatal
IllegalArgumentException: color id must be positive and bit count is less than 19fromStyleDef.makeStyle()(GlitchTip CODEONTHEGO-K, 42 events, still on C-r-1006).IDEColorScheme.load()is@Synchronizedand loads once. Opening a project restores its tabs together, and each editor loaded the same scheme instance on its own IO coroutine; the parallel parses corrupted the non-thread-safeMutableIntIntMap.parseColorValue()no longer catches aputColor()failure and returns the raw ARGB color as a color id. That fallback is what turned a corrupted write into this crash; a failure now reachesloadColorScheme(), which logs it and uses the default scheme.IDEColorSchemeLoadTest: concurrent loads of one scheme, and a second load. Without the fix the eight loader threads hang inMutableIntIntMap.findInsertIndexand a second load doubles the color table (35 to 70).Nothing reloads an instance on purpose:
load()is only reached throughIDEColorSchemeProvider.loadColorScheme()while the provider's cached scheme is null, andSchemeParser.parse()builds its own instance.Reproduce
IDEColorSchemeLoadTestwithout the fix.adb shell am set-debug-app -w com.itsaky.androidide, start the app,jdb -attachandstop thread in com.itsaky.androidide.editor.schemes.IDEColorScheme.load$editor_v8Debug. TwoDefaultDispatcherthreads stop inload()at the same time;resumelets them parse in parallel. With the fix the second thread waits on the lock until the first returns.