Fix watch-mode imports map race#1261
Open
eggrollofchaos wants to merge 1 commit into
Open
Conversation
Snapshot the shared imports map before building the per-language import view so concurrent watch-mode updates cannot resize the dictionary during iteration.\n\nAdd a regression test that mutates the same map from another thread while the import filter is reading it.
|
@eggrollofchaos is attempting to deploy a commit to the shashankss1205's projects Team on Vercel. A member of the Team first needs to authorize it. |
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.
Summary
imports_map.items()before the language-specific call-resolution filter iterates it.Why
This is a read/write race on shared mutable state.
Watch mode can schedule overlapping debounce handlers via
threading.Timer. Those handlers shareself.imports_map: one path may rebuild or update the map while another path is resolving calls and filtering imports by language.Before this change,
_get_lang_importsiterated the live dictionary:If another handler changes the dictionary size during that loop, the reader raises:
Because the exception is raised in the timer thread, it does not fail the watcher process. Unless stderr is being monitored, the process can continue running while the incremental update that hit the race is silently dropped. The watcher keeps logging
Monitoring for file changes, the graph drifts out of sync, and queries can return stale results until a manualcgc index --force.The race can be triggered when edits land close together under typical watch-mode workload such as save-all, branch switch, or format-on-save. Observed on an actively-edited repo.
Fix
The reader now snapshots the dictionary items before filtering:
This matches the existing writer-side pattern that snapshots keys before mutating the same map. It keeps the change focused on the crash without changing the broader watch scheduling behavior.
Related watch-mode scheduling context: #792.
Test plan
python -m pytest tests/unit/tools/test_imports_map_race.py -qpython -m pytest tests/unit/tools/test_imports_map_race.py tests/unit/tools/test_calls_resolution_tiers.py tests/unit/tools/test_python_call_resolution_patterns.py -qruff check src/codegraphcontext/tools/indexing/resolution/calls.py tests/unit/tools/test_imports_map_race.pyblack --check --target-version py312 tests/unit/tools/test_imports_map_race.py