Skip to content

Report shared and service workers ending as page_worker_ended, not page_crashed - #436

Open
archandatta wants to merge 3 commits into
mainfrom
archand/kernel-764/worker-ended
Open

archandatta wants to merge 3 commits into
mainfrom
archand/kernel-764/worker-ended

Conversation

@archandatta

@archandatta archandatta commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • handleTargetCrashed now emits a new page_worker_ended event (category page, with target_id, target_type and url) for shared_worker and service_worker targets. Every other target type keeps emitting page_crashed.
  • adds BrowserPageWorkerEndedEvent to openapi.yaml and to the KnownBrowserTelemetryEvent union, and regenerates oapi.go and category_gen.go
  • adds a real-Chromium regression test, TestPageWorkerEndedChrome, and runs it in the CI "CDP telemetry browser regressions" step
  • documents page_crashed and page_worker_ended in the cdpmonitor README

Why

The monitor mapped every Inspector.targetCrashed to page_crashed. Only three DevTools agent hosts in Chromium send that notification:

  • RenderFrameDevToolsAgentHost::RenderProcessExited sends it only when the renderer terminates abnormally (crashed, killed or failed to launch). These are real crashes.
  • SharedWorkerDevToolsAgentHost::WorkerDestroyed sends it every time a shared worker ends.
  • ServiceWorkerDevToolsAgentHost::WorkerStopped sends it every time a service worker stops.

Dedicated workers, worklets, tabs and the browser target never send it. Because the monitor attaches to shared and service workers with Target.attachToTarget, sessions that never crashed reported a page_crashed each time one of those workers ended, which buried real renderer crashes.

Checked against real Chromium with the monitor attached:

scenario before after
shared worker calls self.close() page_crashed page_worker_ended
tab that owns a shared worker closes page_crashed page_worker_ended
service worker replaced by a newer version page_crashed page_worker_ended
ServiceWorker.stopAllWorkers page_crashed page_worker_ended
service worker left idle for 120 s nothing nothing
dedicated worker closes or terminates nothing nothing
renderer hosting a page and its shared worker is killed page_crashed ×2 page_crashed (page) + page_worker_ended (worker)

Idle service workers are not stopped while a DevTools session is attached. ServiceWorkerVersion skips idle termination when devtools_attached() is true, and the monitor holds a session on every service worker. So idle timeouts do not produce this event; the schema and README say so.

CDP gives no way to tell a worker that ended normally from one whose process died, so both produce page_worker_ended. When a renderer dies, the pages it hosted still report page_crashed.

Unchanged

  • The worker session stays tracked after page_worker_ended. A stopped service worker restarts on the same session and target, and the e2e test checks that its network telemetry keeps flowing and that its next stop reports the event again.
  • page_crashed on page, iframe and background_page targets, and on untracked sessions (target_type: other), behaves as before. The page_crashed schema description notes that data from earlier images can still contain worker page_crashed events.
  • OTLP severity: page_crashed stays ERROR and page_worker_ended gets the default INFO. Both are pinned in TestToLogRecord_Severity.

Generated code

The new schema pins its const names with x-enum-varnames. oapi-codegen v2's enum-collision pass compares names that may already carry a prefix, so adding another enum with the value page changes which existing enums get prefixed: without the pin, the existing unused oapi.Page const is renamed. With the pin, the regenerated oapi.go only adds code; the only removed line is the page_crashed description this PR edits. Regenerating unmodified main produces no diff.

The public API schema change is kernel/kernel#4615. The API passes unknown event types through on read, so the order in which the two land does not matter.

Testing

  • go vet ./... — clean
  • go test -race $(go list ./... | grep -v /e2e$) — all packages pass
  • KERNEL_CDPMONITOR_CHROME_E2E=1 go test -race -count=1 ./lib/cdpmonitor — the full real-Chromium suite passes
  • TestPageWorkerEndedChrome passed 10/10 under -race on Ubuntu Chromium 154 and 10/10 on Chrome for Testing 154.0.8037.92 (the version CI installs), using CI's exact -run filter.
  • Mutation checks: routing worker targets back to page_crashed fails the shared and service worker subtests, and routing page and iframe targets to page_worker_ended fails the renderer-crash subtest plus TestTargetCrashed.
  • The renderer-crash subtest SIGKILLs the renderer PIDs reported by SystemInfo.getProcessInfo. An earlier version used Page.crash, which goes through Chrome's crash handler; it passed locally but timed out once in CI, where findChromium may pick up a different binary.
  • TestTargetCrashedByTargetType (fake CDP server) covers shared_worker and service_worker → page_worker_ended and iframe → page_crashed, and asserts that the session stays tracked.

🤖 Generated with Claude Code

Chromium sends Inspector.targetCrashed on a shared worker's session when the
worker ends and on a service worker's session when it is stopped. The monitor
mapped every targetCrashed to page_crashed, so sessions that never crashed
reported crashes. Worker targets now emit a new worker_ended event; every other
target keeps page_crashed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@archandatta
archandatta marked this pull request as ready for review October 5, 2026 19:36
@archandatta
archandatta requested review from Sayan- and rgarcia October 5, 2026 19:37
archandatta and others added 2 commits October 6, 2026 11:26
…r case

Every other page-category event is page_*. Dedicated workers never send
Inspector.targetCrashed, so only shared and service workers map to the new
event. Document that data from earlier images can still carry page_crashed for
worker targets, and that idle service workers are not stopped while the monitor
holds a session on them.

The real-Chromium crash check now SIGKILLs the renderers instead of sending
Page.crash, so it does not wait on Chrome's crash handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tants alone

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@archandatta archandatta changed the title Report worker targets ending as worker_ended, not page_crashed Report shared and service workers ending as page_worker_ended, not page_crashed Oct 6, 2026
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.

1 participant