perf(acpmux): read background-process output sizes after releasing the session lock (SW-11)
SW-11: stop holding the background-process mutex across filesystem reads
Source investigation: HQ SW-11 follow-up, specific process-history finding.
Root cause
_acpmux/process/list takes each session's std::sync::Mutex<ProcessTable> and used to call ProcessTable::values() while holding it. That method clones and serializes every entry and invokes std::fs::metadata on its outputFile. A slow or remote output file can consequently delay a running agent's process_update from obtaining the same table lock. Global process listings amplify the work across all loaded sessions. The old code scales with completed history.
Change
- Make
ProcessTable::snapshot()clone its ordered records under the lock, then drop the guard. - Resolve
outputBytesand serialize the snapshot after unlocking for both a specified session and global listing. - Preserve live file-size refresh, row order, identifiers, completed status, process-list protocol and the current list's limitations. No new timer, data owner or API.
- A new Rust unit test checks that the file-length callback can acquire the process-table lock, including on a completed task, and that the table's saved data stays unchanged.
Risk and performance
One copy of each process record was already made for every response; this changes when that copy occurs and shortens mutex occupancy. Serialized bytes and list cardinality stay the same. No measured latency gain claimed. File reads can still be slow, but now happen outside the mutex. The separate unpaged 15 MiB cap and O(N²) historical insert paths remain SW-11 follow-ups.
Performance
No perf numbers: this lock-contention fix does the same amount of filesystem and JSON work after releasing the mutex. The new unit test checks lock availability; a same-machine before/after contention or latency benchmark has not run.
Verification
- Source compared against
feat-cmux-next@07088897284b6637a4ddb5763e06ca1601d4aae2. One Rust file changed, one unit test added. - Not run here: Rust/Cargo or fleet CI; the connected environment lacks the repo toolchain. Please run
cargo test -p acpmux --lib -- a_process_list_reads_output_metadata_after_releasing_its_tableinsidecmux-tui/, existing process integration suites, Clippy, and the managed NEXT compile before marking ready. - No UI/layout changes and no screenshots needed.
Changelog: Background-process listings take a snapshot before reading output-file sizes, leaving live process updates free to acquire their session lock.
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Stops acpmux background-process listings from holding a session's process-table mutex while reading output-file sizes, so slow or remote output files no longer delay a running agent's process updates.
- Clones the process rows under the lock, then reads
outputBytesand serializes after releasing it, in both single-session and global listings. - Threads the file-size lookup through an explicit callback, letting a unit test verify it can acquire the process-table lock, including on a completed task.
- Preserves the wire format, row order, and list limitations; no measured latency gain is claimed.