diff --git a/work/projects/cpm-web-extension-breakage-findings.md b/work/projects/cpm-web-extension-breakage-findings.md index 85d102a8..db096407 100644 --- a/work/projects/cpm-web-extension-breakage-findings.md +++ b/work/projects/cpm-web-extension-breakage-findings.md @@ -719,7 +719,9 @@ Outcome: health monitor becomes a classifier; every stuck pixel names its chain. |---|---|---| | Debug sim, wait 35 s idle, navigate | **recovered** | Idle eviction in `wakeUpBackgroundContentIfNecessary` is present in shipping WebKit; retained-failed-view is self-healing, as traced. | | `sudo memory_pressure -S -l critical`, then CMP page | **CPM kept working** | Chain 1 not reproduced. Either `memoryPressureStatusChangedForProcess → TerminateIdleServiceWorkers` is not in this WebKit (it is under `ENABLE(WEB_PROCESS_SUSPENSION_DELAY)`, recent), or `-S` did not reach the WebContent process. Verify with `log stream --predicate 'process CONTAINS "WebKit.Networking" AND eventMessage CONTAINS "terminateIdleServiceWorkers"'`; until then chain 1 is downgraded to "future macOS". | -| Network process kill | pending | Use Debug → Web Extensions → "Terminate WebKit Network Process" (added, calls `_terminateNetworkProcess`) or lldb `[[WKWebsiteDataStore defaultDataStore] _networkProcessIdentifier]`. WebKit XPC processes are launchd children (ppid 1), so they cannot be found by parent PID. | +| Network process kill (Debug → "Terminate WebKit Network Process", `_terminateNetworkProcess`) | **CPM kept working** | Chain 2 not reproduced either. Snapshot after the kill: `network_process_restarted=true`, `extension_context_errors=none`, `background_view_alive=true`, `background_view_create_count=3_to_5`. The background view had been recreated during the session, so WebKit recovers on its own here — via idle eviction or via `webViewWebContentProcessDidTerminate`/`didFailNavigation` of the SW page; which one is not yet known (recorder now logs web-process PID and Network PID per creation to tell them apart). WebKit XPC processes are launchd children (ppid 1), so they cannot be found by parent PID. | + +**Conclusion so far:** on shipping macOS 26.x WebKit, none of the traced "dead worker" triggers reproduce and the retained-failed-view state self-heals. There is currently **no reproduced trigger** for the stuck state; the chains below remain hypotheses ranked by source reading, not by evidence. Fix proposals are parked until a reproduction or production classification exists. ### Implemented (branch `cpm-breakage-pixel`, not yet compiled here — build before trusting) @@ -763,6 +765,19 @@ chrome.runtime.onMessage.addListener((message) => { Keys read by the recorder: `lifecycle` (string), `receivedInitResponse` (bool), `lastSendError` (string|null). Values are sanitized/classified before reaching the pixel. +### Added after the Network-kill check + +- Recorder logs (level `info`, `[CPM Diagnostics]`) on every background view creation: `previousViewAlive`, `previousWebProcessPID`, `previousWebProcessAlive`, `secondsSincePreviousCreation`, `networkProcessPID`, `networkProcessChangedSinceLastCreation`, then the new view's `webProcessPID` one turn later. A recreation with `previousWebProcessAlive=false` or a changed web-process PID means the SW page process died (WebKit's `webViewWebContentProcessDidTerminate` path); `previousWebProcessAlive=true` with ≥30 s gap means idle eviction. +- "Terminate WebKit Network Process" prints a diagnostics snapshot before killing, so before/after can be compared. +- No event hook exists for Network-process termination in the app; WebKit's own `NetworkProcessProxy::didClose` error line is visible in Console.app (`subsystem == "com.apple.WebKit"`, category `Process`) but is not captured by the recorder. + +### Next (data first, no fixes yet) + +1. Repeat the Network-kill with the new logging; read whether the recreation right after the kill is process-death or eviction. +2. Build, run `WebExtensions` tests, land the diagnostics; add the `__ddgCPM` marker to `cpm.js`. +3. Read `debug_web_extension_cpm_messaging_stuck_*` parameters after a release to see which class exists in production. +4. Show the diagnostics parameters in the internal-user stuck notification so reports arrive classified. + ### Not done on purpose - OSLogStore-based counters (per request).