fix: add timeout cleanup regression for browser CDP readiness (#29538) (thanks @AaronWander)

This commit is contained in:
Peter Steinberger
2026-03-02 13:53:06 +00:00
parent 8bccb0032a
commit 99ee26d534
2 changed files with 38 additions and 0 deletions

View File

@@ -60,6 +60,7 @@ Docs: https://docs.openclaw.ai
- Browser/Extension relay stale tabs: evict stale cached targets from `/json/list` when extension targets are destroyed/crashed or commands fail with missing target/session errors. (#6175) Thanks @vincentkoc.
- CLI/Browser start timeout: honor `openclaw browser --timeout <ms> start` and stop by removing the fixed 15000ms override so slower Chrome startups can use caller-provided timeouts. (#22412, #23427) Thanks @vincentkoc.
- Browser/CDP startup diagnostics: include Chrome stderr output and a Linux no-sandbox hint in startup timeout errors so failed launches are easier to diagnose. (#29312) Thanks @veast.
- Browser/CDP startup readiness: wait for CDP websocket readiness after launching Chrome and cleanly stop/reset when readiness never arrives, reducing follow-up `PortInUseError` races after `browser start`/`open`. (#29538) Thanks @AaronWander.
- Docker/Image health checks: add Dockerfile `HEALTHCHECK` that probes gateway `GET /healthz` so container runtimes can mark unhealthy instances without requiring auth credentials in the probe command. (#11478) Thanks @U-C4N and @vincentkoc.
- Docker/Sandbox bootstrap hardening: make `OPENCLAW_SANDBOX` opt-in parsing explicit (`1|true|yes|on`), support custom Docker socket paths via `OPENCLAW_DOCKER_SOCKET`, defer docker.sock exposure until sandbox prerequisites pass, and reset/roll back persisted sandbox mode to `off` when setup is skipped or partially fails to avoid stale broken sandbox state. (#29974) Thanks @jamtujest and @vincentkoc.
- Daemon/systemd checks in containers: treat missing `systemctl` invocations (including `spawn systemctl ENOENT`/`EACCES`) as unavailable service state during `is-enabled` checks, preventing container flows from failing with `Gateway service check failed` before install/status handling can continue. (#26089) Thanks @sahilsatralkar and @vincentkoc.

View File

@@ -27,6 +27,8 @@ function makeBrowserState(): BrowserServerState {
cdpProtocol: "http",
cdpHost: "127.0.0.1",
cdpIsLoopback: true,
cdpPortRangeStart: null,
cdpPortRangeEnd: null,
evaluateEnabled: false,
remoteCdpTimeoutMs: 1500,
remoteCdpHandshakeTimeoutMs: 3000,
@@ -47,6 +49,7 @@ function makeBrowserState(): BrowserServerState {
afterEach(() => {
vi.useRealTimers();
vi.clearAllMocks();
vi.restoreAllMocks();
});
@@ -84,4 +87,38 @@ describe("browser server-context ensureBrowserAvailable", () => {
expect(isChromeCdpReady).toHaveBeenCalled();
expect(stopOpenClawChrome).not.toHaveBeenCalled();
});
it("stops launched chrome when CDP readiness never arrives", async () => {
vi.useFakeTimers();
const launchOpenClawChrome = vi.mocked(chromeModule.launchOpenClawChrome);
const stopOpenClawChrome = vi.mocked(chromeModule.stopOpenClawChrome);
const isChromeReachable = vi.mocked(chromeModule.isChromeReachable);
const isChromeCdpReady = vi.mocked(chromeModule.isChromeCdpReady);
isChromeReachable.mockResolvedValue(false);
isChromeCdpReady.mockResolvedValue(false);
const proc = new EventEmitter() as unknown as ChildProcessWithoutNullStreams;
launchOpenClawChrome.mockResolvedValue({
pid: 321,
exe: { kind: "chromium", path: "/usr/bin/chromium" },
userDataDir: "/tmp/openclaw-test",
cdpPort: 18800,
startedAt: Date.now(),
proc,
});
const state = makeBrowserState();
const ctx = createBrowserRouteContext({ getState: () => state });
const profile = ctx.forProfile("openclaw");
const promise = profile.ensureBrowserAvailable();
const rejected = expect(promise).rejects.toThrow("not reachable after start");
await vi.advanceTimersByTimeAsync(8100);
await rejected;
expect(launchOpenClawChrome).toHaveBeenCalledTimes(1);
expect(stopOpenClawChrome).toHaveBeenCalledTimes(1);
});
});