From ad22e120ab6c7117988db2bebf3499af31ea1391 Mon Sep 17 00:00:00 2001 From: Ryo Kusnadi Date: Fri, 30 Oct 2026 13:21:04 +0700 Subject: [PATCH] fix(cdpmonitor): stop attaching to shared workers Attaching a DevTools session to a shared_worker target can crash Chrome (SEGV in SharedWorkerDevToolsAgentHost) when the page that owns the worker closes. Drop shared_worker from the monitor's tracked target types and from the e2e worker cases that relied on it. Signed-off-by: Ryo Kusnadi --- server/lib/cdpmonitor/monitor.go | 4 +++- server/lib/cdpmonitor/monitor_test.go | 2 +- server/lib/cdpmonitor/network_metrics_chrome_e2e_test.go | 1 - server/lib/cdpmonitor/workers_chrome_e2e_test.go | 1 - 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/lib/cdpmonitor/monitor.go b/server/lib/cdpmonitor/monitor.go index f8691754..7aa3850a 100644 --- a/server/lib/cdpmonitor/monitor.go +++ b/server/lib/cdpmonitor/monitor.go @@ -210,7 +210,9 @@ func (m *Monitor) openConnection(ctx context.Context, devtoolsURL string) error conn := &monitorConnection{ protocol: protocol, surface: browsersurface.New(protocol, - browsersurface.WithAdditionalTargets("worker", "shared_worker", "service_worker", "background_page"), + // shared_worker is deliberately not tracked: attaching a DevTools session to a + // shared worker can crash Chrome when its owning page closes. + browsersurface.WithAdditionalTargets("worker", "service_worker", "background_page"), browsersurface.WithoutLocations(), ), ctx: ctx, cancel: cancel, done: make(chan struct{}), diff --git a/server/lib/cdpmonitor/monitor_test.go b/server/lib/cdpmonitor/monitor_test.go index 09b1df6a..eb47005b 100644 --- a/server/lib/cdpmonitor/monitor_test.go +++ b/server/lib/cdpmonitor/monitor_test.go @@ -197,7 +197,7 @@ func TestSurfaceDiscovery(t *testing.T) { for _, filter := range params.Filter { types = append(types, filter.Type) } - assert.ElementsMatch(t, []string{"page", "iframe", "worker", "shared_worker", "service_worker", "background_page"}, types) + assert.ElementsMatch(t, []string{"page", "iframe", "worker", "service_worker", "background_page"}, types) stopResponder := make(chan struct{}) go listenAndRespond(srv, stopResponder, nil) diff --git a/server/lib/cdpmonitor/network_metrics_chrome_e2e_test.go b/server/lib/cdpmonitor/network_metrics_chrome_e2e_test.go index d3628195..6f676dcf 100644 --- a/server/lib/cdpmonitor/network_metrics_chrome_e2e_test.go +++ b/server/lib/cdpmonitor/network_metrics_chrome_e2e_test.go @@ -182,7 +182,6 @@ func TestAlwaysOnNetworkMetricsChrome(t *testing.T) { } for _, worker := range []struct{ kind, create, request string }{ {"worker", `window.w=new Worker('/worker.js')`, `w.onmessage=e=>resolve(e.data); w.postMessage('/reset');`}, - {"shared_worker", `window.sw=new SharedWorker('/shared.js'); sw.port.start()`, `sw.port.onmessage=e=>resolve(e.data); sw.port.postMessage('/reset');`}, {"service_worker", `await navigator.serviceWorker.register('/service.js'); window.service=(await navigator.serviceWorker.ready).active`, `const c=new MessageChannel(); c.port1.onmessage=e=>resolve(e.data); service.postMessage('/reset',[c.port2]);`}, } { t.Run(worker.kind, func(t *testing.T) { diff --git a/server/lib/cdpmonitor/workers_chrome_e2e_test.go b/server/lib/cdpmonitor/workers_chrome_e2e_test.go index f072d866..836e7943 100644 --- a/server/lib/cdpmonitor/workers_chrome_e2e_test.go +++ b/server/lib/cdpmonitor/workers_chrome_e2e_test.go @@ -70,7 +70,6 @@ func TestNetworkCaptureFromWorkers(t *testing.T) { for _, worker := range []struct{ targetType, path, create, request string }{ {"worker", "/worker.js", `window.testWorker = new Worker('/worker.js')`, `testWorker.onmessage = event => resolve(event.data); testWorker.postMessage(marker);`}, - {"shared_worker", "/shared.js", `window.sharedWorker = new SharedWorker('/shared.js'); sharedWorker.port.start()`, `sharedWorker.port.onmessage = event => resolve(event.data); sharedWorker.port.postMessage(marker);`}, {"service_worker", "/service.js", `await navigator.serviceWorker.register('/service.js'); window.serviceWorker = (await navigator.serviceWorker.ready).active`, `const channel = new MessageChannel(); channel.port1.onmessage = event => resolve(event.data); serviceWorker.postMessage(marker, [channel.port2]);`}, } { t.Run(worker.targetType, func(t *testing.T) {