[2026-09-09] eagle: work/projects/cpm-web-extension-breakage-findings.md
This commit is contained in:
@@ -1072,6 +1072,23 @@ Log confirmation (Network process): `log stream --predicate 'category == "Servic
|
||||
|
||||
Production frequency. The mechanism is unguarded in WebKit; what is unknown is how often P1 loses the race on user machines. The pixel data (probe 2) settles that. No fix proposed until the manual repro above is done.
|
||||
|
||||
### ✅ REPRODUCED 2026-09-10: `kill -9 <background WebContent PID>` → CPM dead in all tabs (new tabs too), self-healed after ~1 min
|
||||
|
||||
Manual run by Alex: `kill -9` on the process reported by "Print CPM Diagnostics Snapshot" (`background_web_process_pid`). Result: banners stop being handled everywhere, new tabs included; revived on its own about a minute later (matches the 30 s idle-unload → next wake → fresh registration cycle).
|
||||
|
||||
This **contradicts** the earlier claim that a dead P1 is cleaned up before any wake. Two candidate sub-mechanisms, both ending in the same state (view alive, `m_backgroundContentIsLoaded` or a pending load, no working SW):
|
||||
|
||||
- **A. Stale SW server state at re-registration.** UI process: `didClose` → `processDidTerminateOrFailedToLaunch` → `webViewWebContentProcessDidTerminate` → `unloadBackgroundWebView` (`WebProcessProxy.cpp:1565-1617`, `WebExtensionContextCocoa.mm:2950-2957`); the next queued content-script message immediately creates the new page in a prewarmed process and registers. Network process: cleanup runs from `NetworkConnectionToWebProcess::didClose` → `unregisterSWConnection` → `SWServer::removeConnection` → `~WebSWServerConnection` → unregister clients → `registration->clear()` (`NetworkConnectionToWebProcess.cpp:470-518`, `SWServer.cpp:1368-1378`, `WebSWServerConnection.cpp:96-105`). If P2's `Register` lands first → "directly reusable registration" against the dead worker (same outcome as the idle-unload race above), or "needs updating" against a registration whose page id is the dead page.
|
||||
- **B. New worker cannot start.** Old registration is gone, but the SW context connection for `webkit-extension://<uuid>` is still being torn down (`m_swContextConnection->stop()`), so the new worker's `createContextConnection` is deferred and the register job does not settle → `_loadServiceWorker` completion never fires → `m_backgroundContentIsLoaded=false`, actions queue, view retained until the 30 s timer → unload → next wake works.
|
||||
|
||||
Discriminating evidence to collect on the next run (kill → immediately reload a tab → within 10 s):
|
||||
1. "Print CPM Diagnostics Snapshot": `background_view_alive`, `background_view_create_count` (2 = new view was created → A or B; 1 = delegate never fired), `background_web_process_pid` (new PID vs 0).
|
||||
2. Our log: `Background web view created #2 … previousWebProcessAlive=false`, then `webProcessPID=<new>`; any `extension_context_errors` (`background_content_failed_to_load` → load actually failed).
|
||||
3. `log stream --predicate 'category == "ServiceWorker" || category == "Extensions"'` during the dead minute: "Found directly reusable registration" / "needs updating" / "No existing registration … constructing a new one", and whether the register job ever resolves.
|
||||
4. Stuck pixel / probe 2 (`background_sw_registration`) if the health monitor fires within the window.
|
||||
|
||||
Production relevance: any death of the background WebContent process — WebKit's own memory kill (`ExceededMemoryLimit`), jetsam on low-memory Macs, a JSC/WebCore crash in the worker — now maps to "CPM dead everywhere until 30 s of silence". `background_view_create_count` + `network_process_restarted=false` + `previousWebProcessAlive=false` in the pixel will measure how often this happens in the field.
|
||||
|
||||
### Side note checked (low value)
|
||||
|
||||
`cpm.js` sends `init` inside the `AutoConsent` constructor and only afterwards calls `chrome.runtime.onMessage.addListener` (`cpm.js:3392-3401`). `tabs.sendMessage(initResp)` requires that listener to be registered in `m_eventListenerFrames` (`WebExtensionContextAPITabsCocoa.mm:483-497`). Both IPCs travel on the same connection and the background round trip is far slower, so this is not a realistic path — noted so nobody re-derives it.
|
||||
|
||||
Reference in New Issue
Block a user