fix(server-s3): list a member's tmux panes asynchronously
A frozen member (SIGSTOPped tmux server) cost every user one synchronous 3 s block of the event loop per minute (F37's back-off ceiling). Member listing now runs through async execFile (same 3 s / SIGKILL / 1 MiB bounds, same back-off) into the listed cache the synchronous readers (liveSessions, listSessions, listOutput) already use: stale-while- revalidate, 15 s max age, cold or failing = that member's panes UNKNOWN (F38 unchanged). A session this process creates or kills is written into the member's cached answer at once, and a list in flight across that change is dropped. Host tmux calls, local mode and every click's call (new-session, send-keys, kill, has-session) are unchanged. review5's stalled-member test now polls for 4 s past the timeout and asserts each poll < 100 ms, event-loop stall < 500 ms and one sudo (old code: first poll 3157 ms).
This commit is contained in:
@@ -267,7 +267,7 @@ Review ran 2026-10-08 (four lenses: root/sudo, cross-member, secrets, local-mode
|
||||
- F34 a developer's extra workspace folder is checked against their own folder (`scope.folderAllowed`, real path) before anything probes it, and again on the path it records (`403 EFOLDER`);
|
||||
- F35 the Codex pool's quota reads a run's rollout only from the `CODEX_HOME` of the account its workspace runs as, never one dated in the future. Accepted ceiling (documented): a member can still forge their own session's reading.
|
||||
- F36 (critical) `GET /api/cc-config/file` never serves the data dir (`isSecretConfigPath`): an analyst read an admin gateway pane's live pane token from `proxy-settings/`, plus `vapid-keys.json` and the database;
|
||||
- F37 every tmux call on a member's socket is bounded (`memberCall`: 3 s, SIGKILL, 1 MiB) with a 60 s back-off — a SIGSTOPped member server froze the event loop for good;
|
||||
- F37 every tmux call on a member's socket is bounded (`memberCall`: 3 s, SIGKILL, 1 MiB) with a 60 s back-off — a SIGSTOPped member server froze the event loop for good. Member LISTING is async (`refreshList`: `execFile`, same limits) into the `listed` cache the sync readers use (stale-while-revalidate, 15 s max age, cold = unknown; a session this process makes or kills is written into the answer at once), so a frozen member no longer costs a 3 s block per back-off on the poll path; a click's call (new-session, send-keys, kill, has-session) is still a sync ≤ 3 s;
|
||||
- F38 a failing member server makes only that member's panes unknown (`liveSessions().has` true for them), never null for everyone; member list errors are cached;
|
||||
- F39 `execIn` and `write-as` (every sync sudo into a member) stop after 5 s (`MEMBER_EXEC`) — a FIFO `include.path` or a FIFO write target hung git and write-as;
|
||||
- F40 transcripts and journals are read with `readLines` (chunked, a line over 64 MiB is skipped, never built) — readline crashed the server on a one-line 512 MB sparse file (import-history, sessions, codex-usage);
|
||||
|
||||
Reference in New Issue
Block a user