Repository navigation
fix computer controls hang - #92
Conversation
Mesa Descriptionusing --sync was ill-advised, it doesn't seem to detect when no mouse movements are necessary to achieve a mousemove, so getting rid of it for now Description generated by Mesa. Update settings |
|
tested with this, which randomly hangs for 15s prior to the change #!/bin/bash
# Test script for scroll down endpoint - runs 10 times with timing
BASE_URL="http://localhost:444"
echo "=== Testing /computer/scroll (vertical down) - 10 iterations ==="
echo ""
total_time=0
times=()
for i in {1..10}; do
start_time=$(date +%s.%N)
curl -X POST "${BASE_URL}/computer/scroll" \
-H "Content-Type: application/json" \
-d '{
"x": 500,
"y": 500,
"delta_y": 3
}' \
-s -o /dev/null
end_time=$(date +%s.%N)
elapsed=$(awk "BEGIN {printf \"%.4f\", $end_time - $start_time}")
times+=($elapsed)
total_time=$(awk "BEGIN {printf \"%.4f\", $total_time + $elapsed}")
echo "Iteration $i: ${elapsed}s"
done
echo ""
echo "=== Results ==="
echo "Total time: ${total_time}s"
avg_time=$(awk "BEGIN {printf \"%.4f\", $total_time / 10}")
echo "Average time: ${avg_time}s" |
There was a problem hiding this comment.
Performed full review of ce46982...429cec9
Analysis
-
Removing the
--syncflag from xdotool mousemove commands eliminates hanging issues but introduces potential race conditions where subsequent mouse actions (clicks, drags) may occur before the cursor reaches its intended position. -
The implementation lacks any alternative synchronization mechanism to ensure cursor positioning completes before dependent operations execute, which could lead to clicks, drags, and scrolls happening at incorrect coordinates.
-
No specific testing has been implemented to verify operations work correctly at boundary conditions, such as when the cursor needs to move significant distances versus when it's already at the target position.
Tip
Help
Slash Commands:
/review- Request a full code review/review latest- Review only changes since the last review/describe- Generate PR description. This will update the PR body or issue comment depending on your configuration/help- Get help with Mesa commands and configuration options
1 files reviewed | 0 comments | Edit Agent Settings • Read Docs
There was a problem hiding this comment.
Performed full review of ce46982...429cec9
Analysis
-
Removing
--synctrades synchronization guarantees for performance, potentially introducing race conditions if any calling code assumes mouse operations complete before the function returns. -
No tests were added to prevent regression or verify that mouse operations no longer hang, leaving the fix vulnerable to future changes.
-
The PR lacks documentation updates explaining the new asynchronous behavior of mouse operations, which could lead to incorrect usage by other developers.
-
No consideration of adding alternative verification logic or retry mechanisms for critical operations where position accuracy is essential.
-
Inconsistent approach to synchronization across the codebase - some mouse operations already didn't use
--sync, suggesting this problem was partially understood before.
Tip
Help
Slash Commands:
/review- Request a full code review/review latest- Review only changes since the last review/describe- Generate PR description. This will update the PR body or issue comment depending on your configuration/help- Get help with Mesa commands and configuration options
1 files reviewed | 0 comments | Edit Agent Settings • Read Docs
## What - Adds runtime browser timezone, locale, and language updates through `PUT /browser/location`, without restarting Chromium. It returns once the running browser confirms the location, so `200` means applied, except in a renderer blocked by a dialog or a long task, which applies it when it resumes. - Adds `GET /browser/location` to the OpenAPI spec, served by the generated server: the accepted location, the location the running browser has confirmed, per-component convergence, and the capability version (`BrowserLocationBundle`, `BrowserLocationComponents`, `BrowserLocationStatus`). It returns `501` when the running browser lacks the location commands. - Persists the accepted location so a restarted Chromium starts with its timezone and `--accept-lang`, applies it again before an image-driven restart returns (failing the restart if it can't), and lets Chromium's timezone watcher follow later `/etc/localtime` changes. - Adds a generated capability manifest (412 locales, 598 IANA timezones) and location validation, with regenerated OpenAPI code. - Exports convergence metrics and blocks the internal location CDP commands on customer DevTools connections, including inside non-flat `Target.sendMessageToTarget` messages. ## Why - The Kernel API (kernel/kernel#4208) changes a running browser's location and must report success only after Chromium has applied it to renderers, workers, timezone state, and network contexts. ## How - **Set:** `PUT /browser/location` applies the location within the request. `200` means the browser confirmed it. A stale or conflicting generation returns `409`; a browser known not to support location returns `501` before anything is stored. If the location doesn't apply, including a browser found unsupported only after acceptance, it returns `500`; the location stays accepted, and resending it retries. The endpoint is separate from `/configure` so the session's proxy can restrict writes to the control plane, which persists the session's location (kernel/kernel#4208). - **Blocked renderers:** a renderer whose main thread is blocked by a dialog or a long task can't acknowledge. After one second, renderers Chromium reports as pending (`renderersPending`) no longer hold back an update whose browser, timezone, and network components converged; they apply it when they resume. `components.renderers_pending` reports them. The image watches them until they acknowledge; if one then reports a component that didn't converge, `applied` is cleared and the location is sent again. - **Ordering:** every location carries a generation (at most 2^53-1, the largest a CDP number holds). The image accepts a higher generation, treats a resend of the accepted location as a retry that the browser must confirm again, and returns `409` for a lower or conflicting one. If Chromium already holds a generation the image didn't send, the image moves above it instead of retrying a stale one. - **Timezone:** ICU names the host timezone after the file `/etc/localtime` resolves to, and tzdata ships 151 of the 598 identifiers as links (`UTC` to `Etc/UTC`, `Europe/Bratislava` to `Europe/Prague`). `/etc/localtime` therefore points at a regular-file copy at `/run/kernel-location/zoneinfo/<id>`, so Chromium reports exactly the requested identifier. `GMT` is hosted as `Etc/GMT`, because ICU treats `GMT` as its built-in fixed zone, which pages report as `+00:00`. The launcher uses the same path. - **Apply:** the accepted location is persisted first. Each round rewrites `/etc/localtime`, sends the location to Chromium once, and polls its acknowledgements on one connection for up to 1.5 s; rounds repeat for up to five seconds. `applied` is set when every component acknowledges, apart from renderers Chromium reports pending. A new attempt clears the previous attempt's error. - **Support:** each Chromium process is probed once with `Browser.getKernelBrowserLocation`. A browser without it makes both `GET` and `PUT /browser/location` return `501`, and a location accepted earlier fails once instead of retrying. - kernel/kernel#4208 calls both endpoints through the generated client. - **Live status:** `GET /browser/location` reads `applied` and its components from the running Chromium, so a restarted or unreachable browser never reports it. - **Restarts:** every restart the image performs (configure, flags, policies, extensions, display) applies the accepted location to the new Chromium before it returns, so `start_url` and later requests don't see the defaults. If the browser doesn't confirm it, configure, flags, policies and extension upload return `500` (configure before navigating, and without restarting Chromium again or rolling back extensions that loaded); a display change logs it, as it does any restart failure. The lifecycle loop keeps retrying either way. - **Restarts the image didn't start** (a crash): Chromium starts with the location's timezone and `Accept-Language`, but its `Intl` locale is the region's until the lifecycle loop applies the location, about two seconds later. On Linux Chromium ignores `--lang` and resolves its locale from the environment to one it ships translations for (this build ships only English ones), so no startup flag or variable can set it; pages that load in that window see the mismatch. - **Startup:** the launcher uses the persisted timezone, then `KERNEL_BROWSER_TIMEZONE`, then `TZ`, and replaces `--accept-lang` with the persisted location's languages. Chromium starts without `TZ` so it observes `/etc/localtime` changes. - **Validation:** values are checked against the image's versioned Chromium/tzdata capability manifest. ## Context - Requires kernel/kernel-browser#92 for the internal CDP commands. Consumed by kernel/kernel#4208, which is gated by the flag in kernel/infra#1601. - Production images build from `kernel-images-private`. After merge, sync this change there; with the current `KERNEL_BROWSER_VERSION`, those images report location as unsupported (`501`), so they're safe to promote. - Bump `KERNEL_BROWSER_VERSION` to a release containing kernel/kernel-browser#92 only after this PR is in the image and kernel/kernel#4208's metro-api is deployed. Customer CDP connections reach Chromium as root browser sessions, so only this PR's proxy filter keeps the location commands off them, and only #4208's passthrough guard keeps customers off `PUT /browser/location`. - No breaking changes: both location endpoints are new. ## Testing & Visuals - `go vet ./...` and `go test -race` for every non-e2e package. New unit tests cover the zoneinfo copy (aliases resolve to the requested identifier), a browser without the location commands (501, 400, no retries), clearing the previous error on retry, moving above Chromium's generation, the generation cap, and nested `Target.sendMessageToTarget` filtering. - E2E on the headless image with the kernel/kernel-browser#92 Chromium build (the reviewed `368c617` and the final `b234c63`): `TestBrowserLocationCapabilities`, `TestBrowserTimezoneFollowsLocaltime`, `TestBrowserLocationRuntimeUpdate`, and the new `TestBrowserLocationEveryTimeZone`, which applies all 598 manifest timezones in about 40 s and checks that the page and an existing worker resolve each as Intl resolves the identifier. On stock Chromium, the new `TestBrowserLocationUnsupportedBrowser` passes (it also runs in CI). - Hot-patched A/B on a running Kernel browser (Unikraft VM), swapping in this branch's image API and launcher and the #92 Chromium: - Before: `UTC` and `US/Eastern` never applied (timezone component false after 5 s). Resending after a failure still reported the old error. With stock Chromium the image accepted a location, changed the timezone but not the locale, and retried indefinitely. Non-flat `Target.sendMessageToTarget` reached the internal commands. - After: `UTC`, `US/Eastern`, `Europe/Bratislava`, `GMT`, `Asia/Calcutta`, and `Europe/Kiev` each applied in about 140 ms, with the page showing what Intl resolves for each. A resend after an injected failure cleared the error at once and applied in 0.17 s. Stock Chromium got `501`/`400`, nothing persisted, and no retries. `Target.sendMessageToTarget` was rejected at the proxy, and with the final #92 build `Target.exposeDevToolsProtocol` page script was rejected by Chromium. - Synchronous configure, hot-patched on a running Kernel browser (Hypeman VM): with stock Chromium, `GET /browser/location` returned `501` and configure `400`; with the #92 build, configure returned `200` after 1.7 s (first update after a Chromium restart) and 112 ms, the status read right after showed the location applied with every component confirmed, and a stale generation returned `409`. Unit tests cover waiting for the apply, a failed apply (`500`, still accepted), a location replaced while waiting (`409`), a browser found unsupported after acceptance (`500`), and a resend of an applied location that the browser can no longer confirm (`500` rather than a `200` from the earlier confirmation). - Self-review follow-up at `97d5d94`: unit tests cover pending renderers (applied after the one-second wait, with the pending count reported), the confirmation rule, re-applying the accepted location after a restart instead of trusting the previous Chromium, and the launcher's language flags. Before the fix, on a running Kernel browser (Hypeman VM), a configure that restarted Chromium with a `start_url` returned `200` with the location unapplied, and that navigation sent `Accept-Language: en-US`. - Hot-patched at `52ad317` (the private sync branch with this PR) with the kernel/kernel-browser#92 build `598340f`, on a running Kernel browser (Hypeman VM): - Stock Chromium: `GET` and `PUT /browser/location` both returned `501`. That nothing is stored on a `501` is covered by a unit test, not checked on the VM. - `PUT` gen 1 `de-DE`/`Asia/Tokyo` returned `200` after 1.7 s (first update after a Chromium restart); a page on httpbin then sent `Accept-Language: de-DE,de;q=0.9`, with `navigator`, `Intl` and the timezone matching. The same generation with other values returned `409`, and `POST /configure` with `browser_location` returned `400 unknown form field`. - With an `alert()` open in a second tab, `PUT` gen 2 `fr-FR`/`Europe/Paris` returned `200` after 1.06 s with `renderers_pending: 1`; once the alert closed, every component reported converged and that tab reported `fr-FR` and `Europe/Paris`. - A configure that restarted Chromium with a `start_url` returned `200` with the location still applied right after, 3 s later and 5 s later, and the `start_url` request sent `Accept-Language: fr-FR,fr;q=0.9`. - Review follow-up at `7c237a1`, hot-patched (as `2616fe8` on the private sync branch) on a running Kernel browser (Hypeman VM) with the #92 build: with a location applied, a configure that restarted Chromium with a `start_url` returned `200` and the page reported `de-DE` in `Intl`, `navigator`, and `Accept-Language`. With stock Chromium swapped in under the same accepted location, the same configure returned `500` ("browser location was not restored after chromium restart") and didn't navigate; the tab Chromium restored read `Intl` `en-US` beside `navigator.language` `de-DE`. Run locally, the #92 build with `--lang=de-DE --accept-lang=de-DE,de` reported `Intl` `en-US`, and `LANGUAGE=de_DE` didn't change it. Unit tests cover the restart failure and a pending renderer that later reports a timezone that didn't converge (sent again, then applied), and fail without the fix. - The e2e suite wasn't re-run on this commit. - Stock CI skips the custom-browser e2e tests; they need `E2E_KERNEL_BROWSER=1` and an image with the #92 build. - Visuals: not applicable; this PR changes image and control-plane behavior only. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches Chromium lifecycle, host `/etc/localtime`, and synchronous API behavior on restart; mis-convergence can fail configure/extension restarts or leave sessions on wrong locale/timezone until retried. > > **Overview** > Adds **runtime browser location** (timezone, locale, languages) via new `GET`/`PUT /browser/location`, with generation ordering, capability validation, durable state, and reconciliation through Kernel CDP commands until Chromium reports component convergence (with special handling for pending renderers). > > The image updates `/etc/localtime` via zoneinfo copies so ICU reports the requested IANA id, persists the accepted bundle for restarts, and **re-applies location after image-driven Chromium starts**—failing the operation if restore does not confirm. The **chromium launcher** boots with that timezone and `--accept-lang` (no `TZ`). Customer DevTools traffic **cannot** call the internal location CDP methods (including nested `Target.sendMessageToTarget`). Prometheus metrics and e2e/unit tests cover the flow. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7c237a1. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: tnsardesai <18272584+tnsardesai@users.noreply.github.com>
using --sync was ill-advised, it doesn't seem to detect when no mouse movements are necessary to achieve a mousemove, so getting rid of it for now
Note
Removes the
--syncflag from allxdotool mousemovecalls to prevent hanging during mouse operations.server/cmd/api/api/computer.go:--syncfromxdotool mousemovein:MoveMouseClickMouseScrollDragMouse(initial move to start point)Written by Cursor Bugbot for commit 429cec9. This will update automatically on new commits. Configure here.