Skip to content

Bug: configure and refresh can race on shared locator configuration #385

@karthiknadig

Description

@karthiknadig

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() writes Context.configuration and then calls locator.configure(&config) for every locator
  • crates/pet/src/jsonrpc.rs: handle_refresh() clones configuration, derives a refresh-scoped config, and then also calls locator.configure(&config) for every locator before discovery
  • crates/pet-core/src/lib.rs: the Locator trait explicitly allows implementations to store configuration internally using Mutex / 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 configure swaps some locators to config B before discovery finishes
  • a refresh-scoped request with searchPaths or 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
  • configure should 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

  1. Make refresh use immutable per-request configuration instead of mutating shared locator state.
  2. Serialize configure against refresh and define clear generation boundaries so a refresh sees either the old config or the new config, never a mix.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIssue identified by VS Code Team member as probable bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions