Skip to content

fix: Race conditions in terminal session management #64

Closed

Description

@mrveiss

Summary

Multiple race conditions were identified and fixed in the terminal session management code. These could cause data corruption, lost sessions, or inconsistent state when multiple concurrent operations access shared dictionaries without synchronization.

Race Conditions Fixed

1. AgentTerminalService.sessions (backend/services/agent_terminal_service.py)

  • Issue: Session dictionary accessed without synchronization
  • Fix: Added _sessions_lock (asyncio.Lock) to protect concurrent session access
  • Impact: Prevents session data corruption during concurrent create/get/close operations

2. SimplePTYManager.sessions (backend/services/simple_pty.py)

  • Issue: PTY session dictionary modified without thread safety
  • Fix: Added _lock (threading.Lock) for atomic check-and-modify operations
  • Impact: Prevents PTY session leaks and resource conflicts

3. Approval workflow race condition (backend/services/agent_terminal_service.py)

  • Issue: Concurrent approval calls could both see pending_approval and execute
  • Fix: Added per-session _approval_locks to serialize approval operations
  • Impact: Prevents duplicate command executions on concurrent approvals

4. Output buffer cleanup race condition (backend/api/terminal.py)

  • Issue: Buffer accessed during cleanup without lock protection
  • Fix: Protected buffer access with _output_lock during cleanup
  • Impact: Prevents data loss during concurrent cleanup operations

5. ConsolidatedTerminalManager dictionaries (backend/api/terminal.py)

  • Issue: Multiple dictionaries (active_connections, session_configs, session_stats) accessed without synchronization
  • Fix: Added _lock (asyncio.Lock) to protect all dictionary operations
  • Impact: Prevents connection tracking inconsistencies and stats corruption

Files Modified

  • backend/services/agent_terminal_service.py
  • backend/services/simple_pty.py
  • backend/api/terminal.py

Testing

  • All fixes follow proper lock acquisition patterns
  • Locks released before async operations to prevent blocking
  • Per-session locks used where appropriate to minimize contention

Activity

  1. mrveiss commented on Nov 16, 2025

    @mrveiss
    OwnerAuthor

    Additional Race Conditions Fixed

    6. DependencyCache race condition (backend/dependencies.py)

    • Issue: Cache check-and-create operation without synchronization
    • Fix: Added _lock (threading.Lock) for atomic get_or_create operations
    • Impact: Prevents duplicate expensive object instantiation

    7. RAGService cache race condition (backend/services/rag_service.py)

    • Issue: Cache read/write/clear operations without synchronization
    • Fix: Added _cache_lock (asyncio.Lock) for all cache operations
    • Impact: Prevents cache corruption during concurrent searches

    8. NPULoadBalancer worker dictionary race conditions (backend/services/load_balancer.py)

    • Issue: Worker dictionary modifications without thread safety
    • Fix: Added _workers_lock (threading.Lock) for all worker dictionary operations
    • Impact: Prevents worker pool corruption during concurrent add/remove/select operations
    • Protected methods: add_worker, remove_worker, get_worker, get_all_workers, select_worker, get_all_workers_status, _health_monitor_loop

    Updated Files List

    • backend/services/agent_terminal_service.py
    • backend/services/simple_pty.py
    • backend/api/terminal.py
    • backend/dependencies.py
    • backend/services/rag_service.py
    • backend/services/load_balancer.py

    Summary

    Total race conditions fixed: 8

    All fixes follow proper synchronization patterns:

    • asyncio.Lock for async-only code paths
    • threading.Lock for sync code paths and mixed contexts
    • Per-session locks for fine-grained concurrency control
    • Atomic check-and-modify patterns to prevent TOCTOU bugs
  2. mrveiss commented on Nov 16, 2025

    @mrveiss
    OwnerAuthor

    ✅ Issue #64 - Race Condition Fixes Verified

    All 5 race conditions documented in this issue have been properly fixed and verified:

    Verified Implementations

    1. AgentTerminalService (backend/services/agent_terminal_service.py)

    • ✅ _sessions_lock = asyncio.Lock() - Protects concurrent session access (line 278)
    • ✅ _approval_locks: Dict[str, asyncio.Lock] - Per-session approval serialization (line 279)
    • ✅ _approval_locks_lock = asyncio.Lock() - Protects the locks dictionary itself (line 280)
    • Proper lock usage at session creation (lines 318-326), cleanup (lines 419, 671, 721), and approval (line 629)

    2. SimplePTYManager (backend/services/simple_pty.py)

    • ✅ _lock = threading.Lock() - Atomic check-and-modify operations (line 366)
    • Protects session dictionary with lock in all critical sections (lines 371, 386, 392, 404)

    3. ConsolidatedTerminalManager (backend/api/terminal.py)

    • ✅ _lock = asyncio.Lock() - Critical dictionary access protection (line 1159)
    • Used consistently across all operations (lines 1186, 1193, 1201, 1220, 1226, 1231, 1241, 1273, 1306)
    • Also uses SimplePTYManager's lock (line 1332)

    4. Output Buffer Protection (backend/api/terminal.py)

    • ✅ _output_lock = asyncio.Lock() - Protects concurrent buffer access (line 274)
    • Used during buffer cleanup operations (lines 428, 1032)

    5. TOCTOU Prevention

    • All implementations use atomic check-and-modify pattern
    • Locks acquired BEFORE checks, held through modification
    • No time-of-check to time-of-use vulnerabilities

    Race Condition Categories Fixed

    Race Condition Type Location Fix Applied
    Session creation/deletion AgentTerminalService _sessions_lock
    Approval handling AgentTerminalService Per-session _approval_locks
    PTY session management SimplePTYManager threading.Lock
    Terminal dictionary ops ConsolidatedTerminalManager asyncio.Lock
    Output buffer cleanup Terminal output _output_lock

    Testing Verification

    The race condition fixes work seamlessly with the existing test suite. No runtime errors or deadlocks observed during concurrent operations.

    Status: ✅ All fixes verified and working correctly
    Author: mrveiss

  3. mrveiss commented on Nov 16, 2025

    @mrveiss
    OwnerAuthor

    ✅ Issue Resolved

    All 8 race conditions have been fixed and committed.

    Commit: 914d15e - fix(concurrency): Add thread-safe locks to prevent race conditions (#64)

    Files Modified:

    • backend/api/terminal.py - ConsolidatedTerminalManager + CommandApprovalManager locks
    • backend/dependencies.py - DependencyCache threading.Lock
    • backend/services/load_balancer.py - NPULoadBalancer worker protection
    • backend/services/rag_service.py - RAGService cache asyncio.Lock
    • backend/services/simple_pty.py - SimplePTYManager session locks

    All TOCTOU bugs and concurrent access issues are now protected with appropriate locking mechanisms.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions