Skip to content

display: converge X root on the configure stop/start resize path#312

Open
Sayan- wants to merge 1 commit into
mainfrom
hypeship/configure-display-converge
Open

display: converge X root on the configure stop/start resize path#312
Sayan- wants to merge 1 commit into
mainfrom
hypeship/configure-display-converge

Conversation

@Sayan-

@Sayan- Sayan- commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Problem

On the batched chromium-configure stop/start path (chromiumDisplayApplyWhileStopped), the Neko screen resize was fire-and-forget: it called setResolutionViaNeko and returned as soon as Neko ACKed, without waiting for the X root to actually reach the requested size. Neko applies screen config asynchronously and can silently drop a reconfig that lands while a previous one is in flight, leaving the root at the dummy DDX default (3840x2160). Chromium then relaunches in --kiosk and maximizes onto the stale root, so the live view shows the browser in a small corner of the frame. Intermittent, and the call returns 200 despite the wrong size.

This branch runs whenever a profile/extension/policy/flags change is bundled with a viewport change in the same configure call. The live-resize path (PatchDisplay) already guards against this (poll + retry, #280); the stop/start branch never got that guard.

Fix

Extract the apply-poll-retry loop into applyResolutionAndConverge and route both paths through it, so the convergence guarantee can't drift between them again. PatchDisplay behavior is unchanged; the stop/start path now waits for the resize to take effect before Chromium relaunches.

Testing

go build, go vet, go test ./cmd/api/api/, gofmt all clean. No unit test (helper needs live X/Neko; matches the untested #280 loop). Live repro not achieved — the race is timing-sensitive and low-probability — but the mechanism is confirmed in code and in prod logs (frequent realized=3840x2160 drops, recovered on the guarded path).

@Sayan- Sayan- requested a review from hiroTamada July 10, 2026 15:51
The batched chromium-configure stop/start path applied the Neko screen
reconfig with a bare setResolutionViaNeko and trusted the RPC return,
unlike the live-resize path (PatchDisplay), which polls the X root and
retries the reconfig when it does not converge.

Neko applies screen configuration asynchronously and can silently drop a
reconfig that lands while a previous one is still in flight, leaving the
X root at the dummy DDX default (3840x2160). When that happens on the
configure path, Chromium is then restarted in --kiosk and maximizes onto
the stale root, so the live view renders the browser in a small corner of
the streamed frame. It is intermittent because it only manifests when the
reconfig is dropped, and the bare RPC returns success without confirming
it took effect.

Extract the apply-poll-retry loop into applyResolutionAndConverge and
route both PatchDisplay and the configure stop/start path through it, so
the two resize paths share one convergence guarantee instead of the guard
living on only one of them (which is how this regression arose).
@Sayan- Sayan- force-pushed the hypeship/configure-display-converge branch from 4a3a4e1 to 89b7801 Compare July 10, 2026 16:33
@Sayan- Sayan- marked this pull request as ready for review July 10, 2026 17:51

@hiroTamada hiroTamada left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reviewed — approving. clean, well-scoped change. the extraction is behavior-preserving on the live-resize side (traced each branch: set-fail, converge-fail, realized≠requested, cdp re-assert all match pre-PR), and routing the configure stop/start path through the shared routine is the right fix — this regression only existed because #280 patched one of the two mirror paths and this closes the other while removing the duplication that let them diverge.

a couple of non-blocking questions worth answering on the record:

Questions (non-blocking)

  • server/cmd/api/api/chromium_configure.go:692-696 — the xrandr sub-branch here still calls setResolutionXorgViaXrandr directly, bypassing applyResolutionAndConverge, so the configure stop/start path relaunches --kiosk with no X-root convergence check when neko is disabled. intended because xrandr applies synchronously (no async drop, so no stale-root window)? if so, a one-line comment saying that would help — and note the helper's doc comment ("the configure stop/start path … must go through here") slightly overclaims, since this sub-path deliberately doesn't. (this branch is unchanged by the PR, so not a regression either way.)
  • server/cmd/api/api/chromium_configure.go:693 — this path can now return 500 (and block up to ~3×10s ≈ 30s on non-convergence) where it previously returned 200 instantly after the neko ACK. that's the intended fail-loud fix, just confirming the new contract + latency ceiling is expected for callers of configure-with-viewport.

Nits

  • server/cmd/api/api/display.go:120-143 — two back-to-back if err == nil { blocks read a little awkwardly now that the first is short; could fold under one guard. pure style, optional.
  • server/cmd/api/api/display.go:542-546 — "every caller must go through here" is convention-only (nothing stops a direct setResolutionViaNeko call). fine as-is, just noting.

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.

2 participants