-
Notifications
You must be signed in to change notification settings - Fork 38
Bug: configure and refresh can race on shared locator configuration #385
Description
Problem
configure and refresh both reconfigure shared locator instances, and locators are allowed to retain mutable configuration via interior mutability. Today those two request handlers can run concurrently.
Relevant code paths:
crates/pet/src/jsonrpc.rs:handle_configure()writesContext.configurationand then callslocator.configure(&config)for every locatorcrates/pet/src/jsonrpc.rs:handle_refresh()clones configuration, derives a refresh-scoped config, and then also callslocator.configure(&config)for every locator before discoverycrates/pet-core/src/lib.rs: theLocatortrait explicitly allows implementations to store configuration internally usingMutex/RwLock
That means an in-flight refresh can observe one configuration snapshot in Context.configuration, but then execute locators after another thread has reconfigured those same shared locator instances.
Why this matters
This is already a correctness risk on its own, and it also complicates work on refresh deduplication / single-flight refreshes.
Examples of failure modes:
- a refresh starts with config A, but a concurrent
configureswaps some locators to config B before discovery finishes - a refresh-scoped request with
searchPathsor kind filtering reconfigures shared locators while another request is also using them - workspace-based locators such as Poetry / Uv can have their workspace directory state overwritten mid-refresh
Desired behavior
Refresh should execute against a stable configuration boundary:
- an in-flight refresh must use one coherent config snapshot for its full duration
configureshould only affect subsequent refreshes, not mutate the effective config of an already-running refresh- refresh-scoped configuration should not leak into other concurrent requests through shared locator state
Possible approaches
- Make refresh use immutable per-request configuration instead of mutating shared locator state.
- Serialize
configureagainst refresh and define clear generation boundaries so a refresh sees either the old config or the new config, never a mix. - Introduce config generation tracking as part of refresh coordination, while separately removing or containing shared mutable locator configuration.
Notes
Issue #383 (deduplicate concurrent refresh requests) can be implemented with a conservative generation-aware join key, but this race is a separate correctness problem and should be tracked independently.