Race condition in _catalog_cache in reference_parser.py #8884

Closed
opened 2026-04-14 03:21:20 +00:00 by HAL9000 · 2 comments
Owner

Metadata

  • Commit Message: fix(tui): add threading lock to protect _catalog_cache in reference_parser
  • Branch: fix/tui-catalog-cache-race-condition

Background and Context

The _catalog_cache in src/cleveragents/tui/input/reference_parser.py is a global variable that is accessed and modified without any locking mechanism. This can lead to a race condition in a multi-threaded environment, where two threads could try to update the cache simultaneously, leading to data corruption.

To Reproduce
Run the application with multiple threads calling parse_references or suggestions concurrently.

Current Behavior
The cache can be corrupted due to a race condition.

# src/cleveragents/tui/input/reference_parser.py:16
_catalog_cache: dict[str, object] = {"cwd": None, "created_at": 0.0, "catalog": None}

# src/cleveragents/tui/input/reference_parser.py:89
_catalog_cache["cwd"] = cwd
_catalog_cache["created_at"] = now
_catalog_cache["catalog"] = catalog

Severity
Medium — the TUI is currently single-threaded, but this could become a problem in the future if the application is multi-threaded.

Expected Behavior

The cache should be updated atomically. A threading.Lock (or threading.RLock) should be used to protect all read and write access to _catalog_cache, ensuring that concurrent calls to parse_references or suggestions cannot corrupt the cache state.

Acceptance Criteria

  • A threading.Lock or threading.RLock is introduced as a module-level variable alongside _catalog_cache
  • All reads and writes to _catalog_cache are protected by the lock (using a with statement)
  • The lock is acquired before checking cache validity and released after any update
  • No deadlocks are introduced
  • Existing behaviour of parse_references and suggestions is unchanged in single-threaded usage
  • Behave scenarios covering concurrent cache access pass without data corruption

Subtasks

  • Introduce _catalog_cache_lock = threading.Lock() at module level in reference_parser.py
  • Wrap all _catalog_cache read/write blocks with with _catalog_cache_lock:
  • Verify no other module-level mutable globals in reference_parser.py are similarly unprotected
  • Add/update Behave scenarios to exercise concurrent access to parse_references and suggestions
  • Run full test suite (nox) and confirm coverage ≥ 97%

Definition of Done

This issue should be closed when:

  • A threading.Lock protects all access to _catalog_cache in reference_parser.py
  • All Behave scenarios pass
  • nox passes with test coverage ≥ 97%
  • The fix is merged to the main branch via a reviewed PR

Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata - **Commit Message**: `fix(tui): add threading lock to protect _catalog_cache in reference_parser` - **Branch**: `fix/tui-catalog-cache-race-condition` ## Background and Context The `_catalog_cache` in `src/cleveragents/tui/input/reference_parser.py` is a global variable that is accessed and modified without any locking mechanism. This can lead to a race condition in a multi-threaded environment, where two threads could try to update the cache simultaneously, leading to data corruption. **To Reproduce** Run the application with multiple threads calling `parse_references` or `suggestions` concurrently. **Current Behavior** The cache can be corrupted due to a race condition. ```python # src/cleveragents/tui/input/reference_parser.py:16 _catalog_cache: dict[str, object] = {"cwd": None, "created_at": 0.0, "catalog": None} # src/cleveragents/tui/input/reference_parser.py:89 _catalog_cache["cwd"] = cwd _catalog_cache["created_at"] = now _catalog_cache["catalog"] = catalog ``` **Severity** Medium — the TUI is currently single-threaded, but this could become a problem in the future if the application is multi-threaded. ## Expected Behavior The cache should be updated atomically. A `threading.Lock` (or `threading.RLock`) should be used to protect all read and write access to `_catalog_cache`, ensuring that concurrent calls to `parse_references` or `suggestions` cannot corrupt the cache state. ## Acceptance Criteria - [ ] A `threading.Lock` or `threading.RLock` is introduced as a module-level variable alongside `_catalog_cache` - [ ] All reads and writes to `_catalog_cache` are protected by the lock (using a `with` statement) - [ ] The lock is acquired before checking cache validity and released after any update - [ ] No deadlocks are introduced - [ ] Existing behaviour of `parse_references` and `suggestions` is unchanged in single-threaded usage - [ ] Behave scenarios covering concurrent cache access pass without data corruption ## Subtasks - [ ] Introduce `_catalog_cache_lock = threading.Lock()` at module level in `reference_parser.py` - [ ] Wrap all `_catalog_cache` read/write blocks with `with _catalog_cache_lock:` - [ ] Verify no other module-level mutable globals in `reference_parser.py` are similarly unprotected - [ ] Add/update Behave scenarios to exercise concurrent access to `parse_references` and `suggestions` - [ ] Run full test suite (`nox`) and confirm coverage ≥ 97% ## Definition of Done This issue should be closed when: - A `threading.Lock` protects all access to `_catalog_cache` in `reference_parser.py` - All Behave scenarios pass - `nox` passes with test coverage ≥ 97% - The fix is merged to the main branch via a reviewed PR --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.0.0 milestone 2026-04-14 03:24:42 +00:00
Author
Owner

⚠️ Duplicate detected after creation.

This issue is a duplicate of #8454reference_parser._catalog_cache global dict is not thread-safe — concurrent Textual workers cause race conditions — which covers the exact same problem with greater detail and is already State/Verified.

Closing this issue in favour of #8454. Please track the fix there.


Automated by CleverAgents Bot
Agent: new-issue-creator

⚠️ **Duplicate detected after creation.** This issue is a duplicate of #8454 — *`reference_parser._catalog_cache` global dict is not thread-safe — concurrent Textual workers cause race conditions* — which covers the exact same problem with greater detail and is already `State/Verified`. Closing this issue in favour of #8454. Please track the fix there. --- **Automated by CleverAgents Bot** Agent: new-issue-creator
Author
Owner

Triage Decision: DUPLICATE — Closing as Wont Do

This issue is a duplicate of #8454 (reference_parser._catalog_cache global dict is not thread-safe — concurrent TUI sessions), which is already verified and open with MoSCoW/Must Have, Priority/High.

Please track this work in #8454.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

❌ **Triage Decision: DUPLICATE — Closing as Wont Do** This issue is a duplicate of #8454 (reference_parser._catalog_cache global dict is not thread-safe — concurrent TUI sessions), which is already verified and open with MoSCoW/Must Have, Priority/High. Please track this work in #8454. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#8884
No description provided.