Skip to content

fix(next): the remote-localhost proxy's trust scan runs one at a time off the cooperative pool - #32423

Merged
teamleaderleo merged 6 commits into
feat-cmux-nextfrom
lane/rs-crashes-proxy-trust
Nov 2, 2026
Merged

teamleaderleo merged 6 commits into
feat-cmux-nextfrom
lane/rs-crashes-proxy-trust

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

What

The remote-localhost proxy decides whether a connection on a machine's listener comes from this app or one of its Chromium helpers by scanning the process table: proc_pidinfo(PROC_PIDLISTFDS) plus one proc_pidfdinfo per socket of the app and of every child. That scan ran as plain blocking code inside the connection's task, once per connection, with up to 256 connections allowed. A busy app with thousands of fds, plus a local process opening connections to the listener port, could hold cooperative-pool threads in those calls and stall unrelated async work.

PeerScan (owned by the proxy) now runs the scan on its own serial queue: one scan at a time, none on the cooperative pool. At most 32 scans are queued or running; past that a caller is untrusted at once. The queue's label is listed in plans/cmux-next/threading-model.md with an owner row. The connection awaits it. The trust decision and its order against the credential check are unchanged.

Tests

PeerProcessScanTests (6 tests): scans never overlap (peak 1 across 32 callers), a canary task on the cooperative pool finishes while 64 scans are pending, a stalled scan does not hold the callers behind it (they answer false at the timeout and their scans are skipped), a cancelled caller answers at once and its scan is skipped, callers past the pending limit answer at once, and a peer that is not this process is not trusted.

No capture: no visible change; the check's result is the same.

Risk

Small, in CmuxNextRemoteLocalhost. A connection's trust check can now wait behind earlier scans (each a few milliseconds). The wait is bounded at 2 s and cancellation-aware: a timed-out or cancelled caller answers "not trusted" at once and its queued scan is skipped, so a stalled scan cannot hold connection slots. The 10 s head deadline stays armed through the wait. No new timer or observer: the queue is a single static serial queue with no loop.

🤖 Generated with Claude Code

Agent session: agent session


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes the remote-localhost proxy's trust scan so it no longer runs on the cooperative pool, where a flood of local connections could stall unrelated async work.

  • Runs each scan on a dedicated serial queue, one at a time, with the proxy owning its PeerScan instance.
  • Bounds the wait at 2 s and the pending scans at 32; a timed-out, cancelled, or refused caller answers "not trusted" at once and its queued scan is skipped, settled in one critical section so it cannot race the scan finishing.
  • The trust decision and its order against the credential check are unchanged; the 10 s head deadline stays armed through the wait.
  • Adds PeerProcessScanTests covering non-overlapping scans, cooperative-pool liveness, stalled-scan timeouts, cancellations, the pending limit, and untrusted peers.

Written for commit f8f62a7. Summary will update on new commits.

View guided diff Turn on auto-fix

… off the cooperative pool

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1d26303068661ea54f28
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review f8f62a7: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr32423 -f ref=lane/rs-crashes-proxy-trust -f platform=macos -f backend_mode=local

Shipped in:

The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/41497919334 at f6b340f failed: cmux-next crash ends the app, cmux-next daemon tests.
Those jobs last passed at ac1dcde. This pull request is one of 5 merged since: #32423, #32457, #32494, #32495, #32490.
If the failure is in your change, fix forward on feat-cmux-next. Pull requests run only the tiers their paths reach (docs/ci/cmux-next-tiers.md); label a batch PR full-ci to run them all before merging.

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 2, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, router-review): BLOCK at d82809e

BLOCK at d82809e

Visual verdict: no images; Leo tries the build

  1. [P1] [blocking] ProxyConnection.swift:56-57 / PeerProcess.swift:56-62 — The 10-second deadline is canceled before awaiting the serial scan, and isTrustedOffPool has no cancellation or timeout path. Queued machine-listener requests can therefore hold all 256 connection slots beyond the advertised deadline, potentially indefinitely if a scan stalls. Keep the trust wait bounded and cancellation-aware.

…the scan test builds

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1d26303068661ea54f28
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high, sweep, via the review router; full diff from merge base d94d657 to this head): BLOCK at d82809e

[P2] [blocking] Packages/macOS/CmuxNext/Sources/CmuxNextRemoteLocalhost/PeerProcess.swift:45 - Every machine-listener request queues an uncancellable process scan on one global serial queue; because ProxyConnection cancels its deadline before awaiting it, an unauthenticated local client can flood the listener and stall trusted connections while queued tasks accumulate - bound/coalesce scans and make queued work cancellation/deadline-aware, keeping the authorization deadline active through the scan.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at f5169b8

Reviewer: codex gpt-6-astra high, fast tier.

Follow-ups: 1. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at f5169b8

Visual verdict: unchanged by this diff

  1. [P2][follow-up] ScanRequest.cancel() updates cancelled and settles in separate critical sections (PeerProcess.swift:110). A scan can finish between them, store true, and resume a timed-out or cancelled caller as trusted, violating the documented false-on-cancel/timeout behavior. Make cancellation atomically claim the result, or have finish reject cancelled requests.

Follow-ups:

  • [P2][follow-up] Fix the cancellation/finish race in ScanRequest.

@cmux-bot cmux-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmux-bot approves f5169b8: an independent review passed this exact head (router-review receipt by teamleaderleo). A push needs a new review; a later BLOCK at this head dismisses this approval.

… stalled-scan tests wait for the stall

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1d26303068661ea54f28
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol xhigh, next-review): BLOCK at e8fa32a

BLOCK at e8fa32a

Visual verdict: no images; Leo tries the build

  1. [P1] [blocking] Packages/macOS/CmuxNext/Sources/CmuxNextRemoteLocalhost/PeerProcess.swift:46 adds a new queue label, com.cmuxterm.next.remote-localhost.peer-scan, without registering it in plans/cmux-next/threading-model.md. The enforced thread-doc guard rejects this new DispatchQueue and fails the prepush/CI checks.

  2. [P1] [follow-up] PeerProcess.swift:74 enqueues one GCD block per request, but timeout/cancellation only settles ScanRequest; queued blocks remain. If a scan stalls or arrivals outpace scans, connection slots recycle after 2 seconds while the serial queue grows without bound. Add bounded pending admission or a worker queue that drops canceled requests before enqueueing.

Follow-ups: 2. Bound the pending scan queue to prevent unbounded memory growth during a stalled or overloaded scan.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol high, sweep, via the review router; full diff from merge base d94d657 to this head): SHIP at e8fa32a

No P1/P2 findings.

teamleaderleo and others added 2 commits November 2, 2026 16:43
…und the scans pending behind a stall

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1d26303068661ea54f28
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol xhigh, router-review): BLOCK at fe6989f

BLOCK at fe6989f

Visual verdict: no images; Leo tries the build

  1. [P1][blocking] Packages/macOS/CmuxNext/Sources/CmuxNextRemoteLocalhost/PeerProcess.swift:165 — The escaping queue.async closure accesses pending without self. Swift 6 rejects this capture, so the target does not compile. Capture self explicitly or capture pending locally.

  2. [P2][follow-up] Packages/macOS/CmuxNext/Sources/CmuxNextRemoteLocalhost/ProxyConnection.swift:57 — If the head arrives near the 10-second deadline, the timer can cancel client while trustedRoute() waits, but run() continues and may open a tunnel and forward a request anyway. Check cancellation after the trust wait before routing/opening.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, sweep, via the review router; full diff from merge base d94d657 to this head): SHIP at f8f62a7

No P1/P2 findings.

@teamleaderleo
teamleaderleo merged commit 72e65a5 into feat-cmux-next Nov 2, 2026
164 of 167 checks passed
@teamleaderleo
teamleaderleo deleted the lane/rs-crashes-proxy-trust branch November 2, 2026 17:56
@lawrencecchen

Copy link
Copy Markdown
Contributor

Swift logic follow-up (tip watcher swift-logic row, STATUS 13027 "SWIFT LOGIC CULPRITS"; lead order).

This PR raised swift_logic_lines by +52 at its merge commit 72e65a5: scripts/cmux-next/swift-logic-lines.py before and after the merge, with the same table (the tip's, c6be943). The largest declarations of the rise:

  • class PeerScan in Packages/macOS/CmuxNext/Sources/CmuxNextRemoteLocalhost/PeerProcess.swift: +47 lines counted as Swift logic (no row in plans/cmux-next/swift-logic-classes.tsv)
  • class ProxyConnection in Packages/macOS/CmuxNext/Sources/CmuxNextRemoteLocalhost/ProxyConnection.swift: +3 lines counted as Swift logic (its row counts it as logic)
  • class RemoteLocalhostProxy in Packages/macOS/CmuxNext/Sources/CmuxNextRemoteLocalhost/RemoteLocalhostProxy.swift: +2 lines counted as Swift logic (its row counts it as logic)

plans/cmux-next/layer-ownership.md says Rust owns every state, list and rule and Swift is the platform shell. Please move the new logic of this PR in a follow-up: to Rust (the crate that owns the area; the owner lists in STATUS 12147-12165 name the target per area), or at least out of the app into its package. If a declaration above is platform code (AppKit, Core Animation, OS calls, strings, tokens, DEBUG tooling), reply here and the table gets a PLATFORM row with your reason instead.

The swift-logic row is a report, not a gate: nothing blocks on this comment.

This branch was previously deployed

1 inactive deployment
ci-routing-agent — f8f62a74 Deployed Nov 2, 2026 by teamleaderleo via cmux-tui tree preflight #102103
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants