Skip to content

refactor: per-session locking in SessionManager (audit round 3, P7) - #29

Merged
mizu-jun merged 1 commit into
masterfrom
refactor/p7-per-session-locks
Jul 5, 2026
Merged

refactor: per-session locking in SessionManager (audit round 3, P7)#29
mizu-jun merged 1 commit into
masterfrom
refactor/p7-per-session-locks

Conversation

@mizu-jun

@mizu-jun mizu-jun commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Implements finding P7 from the round 3 audit (docs/plans/audit-round3-2026h2.md).

Problem

The sessions map was a single Arc<Mutex<HashMap<String, Session>>>. Every IPC operation locked the whole map, so any action on one session (key input, resize) blocked every other session and client behind the same lock.

Change

Map is now Arc<Mutex<HashMap<String, Arc<Mutex<Session>>>>>.

  • New SessionManager::session_arc(name) holds the map lock only to look up and clone a session's Arc, then releases it. Callers lock just that one session — the canonical by-name path.
  • All ~50 IPC call sites (pane / window / session / file dispatch, ws, handler) and the internal manager methods migrated to this pattern.
  • Lock order (deadlock prevention): map → session → workspace_state. No two of {session, workspace_state} are ever held together. list_workspaces, rename_workspace, delete_workspace, to_snapshot, and poll_foreground_processes were restructured to clone session Arcs under the map lock, then lock each session separately.
  • pane_snapshot (sync, WASM plugin host) uses try_lock on both the map and each session, failing closed as before.

Per-session window/pane lock granularity is intentionally left as a future item.

Tests

  • New concurrent_manager_ops_do_not_deadlock: drives workspace + sessions-map + snapshot paths from 8 concurrent tasks under a 10s timeout — PTY-free, so it runs in CI (unlike the session-creating tests, which spawn PTYs and are #[ignore]).
  • cargo test (all crates, 26 suites), cargo clippy --all-targets -- -D warnings, cargo fmt --check all green.

Notes

The migration bulk was mechanical (same transform at every call site); reviewed for the lock-order invariant above. Real throughput improvement can't be measured headless — the win is that per-session operations no longer serialize on one global lock.

Remaining deferred audit items: P3, P6 (profiling), P5, R5/A5 (PROTOCOL bump).

The sessions map was a single Arc<Mutex<HashMap<String, Session>>>, so any
operation on one session (key input, resize) blocked every other session and
client behind the same lock.

Change the map to Arc<Mutex<HashMap<String, Arc<Mutex<Session>>>>>. The new
SessionManager::session_arc(name) holds the map lock only to look up and clone
a session's Arc, then releases it; callers lock just that one session. All ~50
IPC call sites (pane/window/session/file dispatch, ws, handler) and the
internal manager methods were migrated to this pattern.

Lock order (deadlock prevention): map -> session -> workspace_state, and no two
of {session, workspace_state} are ever held simultaneously. list_workspaces,
rename_workspace, delete_workspace, to_snapshot, and poll_foreground_processes
were restructured to clone session Arcs under the map lock and then lock each
session separately, never overlapping with workspace_state.

pane_snapshot (sync, called from the WASM plugin host) uses try_lock on both
the map and each session, failing closed as before.

Tests: new concurrent_manager_ops_do_not_deadlock drives the locking paths from
8 tasks under a 10s timeout (PTY-free, runs in CI). cargo test (all crates) /
clippy --all-targets -D warnings / fmt --check green.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

Coverage report


Generated by cargo llvm-cov (workspace minus nexterm-client-gpu and nexterm-i18n).

@mizu-jun
mizu-jun merged commit 1afa344 into master Jul 5, 2026
12 checks passed
@mizu-jun
mizu-jun deleted the refactor/p7-per-session-locks branch July 5, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant