[2026-10-08] eagle: work/projects/cpm-web-extension-breakage-session-summary-2026-10-07.md work/projects/cpm-web-extension-repro-and-fix-2026-10-08.md
This commit is contained in:
1 parent
0818e81681
commit
a304ee1c43
2 files changed
+39
-11
No files matched your search
@@ -258,7 +258,7 @@ Error 6 частично ложится на путь `refreshCpmDashboardState`
|
||||
- **Полный отказ:** падение Network-процесса оставляет background живым, а worker мёртвым; ломаются все вкладки и уже открытые документы; M4 чинит только новые навигации. Закрыто watchdog'ом, который перезапускает только background-процесс.
|
||||
- **Смерть worker'а при живом Network-процессе** (SPI или удаление SW-регистраций) из приложения не обнаружить; закрыто перезапуском background по первому сбою (стоит одну навигацию).
|
||||
- Сверка с данными 5 октября: смена Network-процесса заметно чаще в группе «без видимой ошибки» (iOS 17–21%, macOS 30–45% против ~10% и 1–3% в остальных группах), но это не доказательство — нужен параметр `network_replaced_since_view`. Error 6 на iOS (~1/3 строк), привязка вкладок и большая часть «здоровых» сбоев фиксами не покрыты.
|
||||
- **Error 6 (iOS):** механизм воспроизведён на macOS — процесс нового background'а не выполняется ≥30 с во время загрузки → таймаут SW → error 6 с продовой сигнатурой. Вероятный iOS-путь: будильник CPM `cpm-summary` будит background, пока приложение в фоне и процессы приостановлены. Ждёт подтверждения на устройстве с iOS 26 (подключённый iPhone на 18.1).
|
||||
- **Error 6 (iOS):** причина найдена в коде WebKit — при пробуждении 30-секундный idle-таймер выгрузки взводится до окончания загрузки service worker'а; загрузка дольше 30 с закрывается → error 6 (продовый порядок `dealloc → error:6 → view`). Тест-репро на macOS есть. На iPhone с iOS 26.7.1 в четырёх сценариях (фон, будильник CPM, звук в фоне) не воспроизвёлся; добавлена телеметрия `bg_load_error_app_state` / `bg_load_error_after`, чтобы прод показал условия.
|
||||
- **Привязка вкладок (macOS):** гипотеза «флаг мигает → новый менеджер» отброшена — флаг всегда `enabled`; проверяются popup-вкладки и пересборка user scripts.
|
||||
- Фикс не закоммичен; открытые вопросы (feature flag, телеметрия, SPI, сборка приложений, ping в extension) — в заметке по ссылке.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ tags:
|
||||
- Оба класса отказа воспроизведены, причины найдены, фикс на стороне app написан, тесты зелёные.
|
||||
- Сверка с данными 5 октября: механизм краша Network-процесса подкреплён лишь частично (20–45% «здоровых» `stuck`); error 6 на iOS (~1/3 строк), привязка вкладок и большая часть «здоровых» сбоев фиксами не покрыты. Нужна телеметрия до или вместе с фиксами (раздел «Телеметрия для валидации»).
|
||||
- Весь пакет: 490 тестов, 0 падений (repro-тесты без env пропускаются). SwiftLint `--strict` чистый.
|
||||
- **8 октября:** разбор непокрытых групп ведётся в отдельном worktree `alex/cpm-web-extension-remaining-failures` (без фиксов, как в проде) — см. раздел «Непокрытые группы: расследование». Error 6 воспроизведён на macOS, найден естественный iOS-путь (будильник CPM будит background, пока приложение в фоне); ждёт подтверждения на устройстве с iOS 26.
|
||||
- **8 октября:** разбор непокрытых групп ведётся в отдельном worktree `alex/cpm-web-extension-remaining-failures` (без фиксов, как в проде) — см. раздел «Непокрытые группы: расследование». Error 6: причина найдена в коде WebKit (30-секундный idle-таймер взводится до окончания загрузки), есть тест-репро на macOS; на iPhone с iOS 26.7.1 не воспроизвёлся; добавлена телеметрия `bg_load_error_app_state` / `bg_load_error_after` (не закоммичено).
|
||||
|
||||
## Что нашли
|
||||
|
||||
@@ -118,16 +118,43 @@ WebKit (`WebExtensionContextCocoa.mm`): error 6 ставится, когда `_l
|
||||
| Background-скрипт бросает на верхнем уровне / нет `browser`/`chrome` | error 6 **без** кода 7 — точная продовая сигнатура «только 6», но продовой причины падения скрипта не нашлось |
|
||||
| **Новый процесс background заморожен ≥30 с во время загрузки** | **таймаут загрузки SW → `background none` + error 6**, цепочка `view, proxy_on, unresponsive, error:6, dealloc`; 10 с — error 6 нет; после разморозки работает |
|
||||
|
||||
**Естественный путь на iOS (гипотеза):** в настоящем приложении в iOS Simulator видно, что CPM сам будит background будильником `cpm-summary` (через 2 мин после активности, шлёт `autoconsent_summary`) — **в том числе когда приложение в фоне**. На устройстве RunningBoard не даёт фоновому приложению держать новый WebContent-процесс активным → процесс приостанавливается посреди загрузки SW → таймаут ~30 с → error 6. Объясняет, почему error 6 почти только на iOS (579 против 3).
|
||||
**Причина в коде WebKit (подтверждено):** `WebExtensionContext::wakeUpBackgroundContentIfNecessary` (`WebExtensionContext.cpp`) первым делом вызывает `scheduleBackgroundContentToUnload()` — взводит 30-секундный idle-таймер выгрузки **до** того, как service worker загрузился. Если загрузка не закончилась за 30 с, таймер вызывает `unloadBackgroundContentIfPossible` → `unloadBackgroundWebView()` → view закрывается посреди загрузки → колбэк `_loadServiceWorker(success=false)` → error 6. Это объясняет продовый порядок `dealloc → error:6 → view` и репро с заморозкой: 45 с → error 6, 10 с → нет.
|
||||
|
||||
Ограничения проверки:
|
||||
- Тесты пакета в iOS Simulator непоказательны: процесс `xctest` не получает RunningBoard assertions (`Failed to acquire RBS assertion`), background не работает с самого начала.
|
||||
- В приложении в симуляторе фоновое приложение не приостанавливается (background живёт 40–50 с и грузится), поэтому сам error 6 там не появляется.
|
||||
- **Нужно устройство с iOS 18.4+ (лучше 26.x).** Подключённый iPhone 12 mini — на iOS 18.1: CPM-extension там не включается (`@available(iOS 18.4)`). Сборка DDG iOS (Debug), локальный HTTP-сервер со страницами и сценарии через `simctl`/`devicectl` готовы.
|
||||
**Тест-репро на macOS** (`Tests/WebExtensionsTests/CPMRepro/CPMReproBackgroundLoadFailureTests.swift`, worktree `alex/cpm-web-extension-remaining-failures`), с проверками, все 9 зелёные:
|
||||
|
||||
Сценарий для устройства: открыть страницу → свернуть приложение → ждать 2–3 мин (будильник `cpm-summary`) → вернуться → навигация; снимать логи `WebExtensions` (`[CPM Diagnostics]`, `Context error`).
|
||||
```bash
|
||||
cd SharedPackages/WebExtensions && CPM_REPRO=1 swift test --filter CPMReproBackgroundLoadFailureTests
|
||||
```
|
||||
|
||||
Возможный фикс, если подтвердится: при возврате приложения на передний план, если `context.errors` содержит error 6 или background мёртв, — перезапустить background; либо не давать будильнику будить background, пока приложение в фоне (изменение extension или WebKit).
|
||||
- `testBackgroundStalledPastUnloadTimerFailsToLoad` — новый процесс background заморожен на 45 с при пробуждении → `context_errors` = только `:6`, `bg_load_error_after=25s_to_35s`, `bg_load_error_app_state=active`, следующее пробуждение работает.
|
||||
- `testBackgroundStalledLessThanUnloadTimerLoads` — 10 с → error 6 нет.
|
||||
- `testMissingExtensionFilesFailWithAFileError`, `testThrowingWorkerScriptFailsToLoad`, `testWorkerWithoutExtensionBindingsFailsToLoad` — error 6 через `under_5s` (отличаются от таймера по новому параметру).
|
||||
- `testWakeWithoutInterferenceLoads`, `testFrozenNetworkProcessDoesNotFailTheLoad`, `testNetworkProcessCrashBeforeWakeDoesNotFailTheLoad`, `testBackgroundKilledDuringLoadDoesNotFailTheLoad` — error 6 нет.
|
||||
|
||||
**iOS Simulator:** тесты пакета непоказательны — процесс `xctest` не получает RunningBoard assertions, background не работает с начала. Приложение DDG в симуляторе работает, но фоновое приложение не приостанавливается. Видно, что CPM сам будит background будильником `cpm-summary` (через 2 мин после активности), в том числе когда приложение в фоне.
|
||||
|
||||
**iPhone 12 mini, iOS 26.7.1, debug-сборка DDG (установлена поверх 7.221.0)** — error 6 **не воспроизвёлся**:
|
||||
|
||||
| Сценарий | Результат |
|
||||
|---|---|
|
||||
| Свернуть на 2,5 мин при стоящем будильнике | приложение приостановлено целиком, будильник срабатывает при возврате, загрузка ~0,1 с |
|
||||
| Разбудить и сразу свернуть (4 задержки) | загрузка успевает за ~0,1 с |
|
||||
| Звук играет в фоне, будильник будит background в фоне | background создаётся и грузится, через 30 с штатно выгружается |
|
||||
| Фоновый запуск системой (`--no-activate`) | не проверено: консоль не подключается, `log collect` требует `sudo` |
|
||||
|
||||
Вывод: на ненагруженном устройстве загрузка всегда укладывается в 30 с. Оставшиеся кандидаты: нехватка памяти / jetsam на нагруженных устройствах; фоновый запуск системой (`fetch`/`processing`), когда приложение приостанавливают посреди загрузки, а при возврате просроченный таймер срабатывает раньше её завершения. Решено не подбирать условия вслепую, а добавить телеметрию (ниже).
|
||||
|
||||
**Телеметрия для error 6 — реализована (не закоммичено, worktree `alex/cpm-web-extension-remaining-failures`):**
|
||||
|
||||
- Новые параметры у всех 8 CPM-пикселей с диагностикой на iOS и macOS (`debug_web_extension_cpm_initialization_failed_after_*`, `debug_web_extension_cpm_messaging_stuck_*`):
|
||||
- `bg_load_error_app_state` — состояние приложения, когда контекст последний раз записал error 6: `none` / `active` / `inactive` / `background`;
|
||||
- `bg_load_error_after` — время от создания view, чья загрузка упала, до error 6: `none` / `under_5s` / `5s_to_25s` / `25s_to_35s` / `over_35s`. `25s_to_35s` — idle-таймер WebKit.
|
||||
- Код: `CPMAppSessionDiagnostics` получил провайдер `applicationState` (iOS — `UIApplication.applicationState`, macOS — `NSApp.isActive`); `CPMMessagingDiagnosticsRecorder` фиксирует состояние и задержку в момент записи error 6, сбрасывает при новом контексте; `CPMMessagingDiagnostics` отдаёт параметры (`none`, если ошибки не было; опускает, если неизвестно).
|
||||
- JSON5: `params_dictionary.json5` и определения (iOS `debug_pixels.json5`, macOS `web_extensions.json5`); `validate-pixel-defs` проходит на обеих платформах.
|
||||
- Тесты: 2 unit-теста в `CPMMessagingDiagnosticsTests.swift` (захват состояния и задержки, бакеты) + сквозная проверка в тесте-репро. Весь пакет: 459 тестов, 0 падений. SwiftLint чистый.
|
||||
- Ожидаемое чтение данных: `25s_to_35s` + `background` → загрузка, застрявшая из-за фона; `25s_to_35s` + `active` → медленная загрузка на переднем плане (память, нагрузка); `under_5s` → сломанный скрипт или файлы.
|
||||
|
||||
Возможный фикс после данных: при возврате приложения на передний план, если `context.errors` содержит error 6, — перезапустить background; либо не будить background, пока приложение в фоне (изменение extension или WebKit).
|
||||
|
||||
### Привязка вкладок на macOS (`tab_controller_match=false` + нет scripts, ~100 строк)
|
||||
|
||||
@@ -176,9 +203,10 @@ WebKit (`WebExtensionContextCocoa.mm`): error 6 ставится, когда `_l
|
||||
- [ ] **Риск перезапуска по первому сбою.** Первых сбоев много (~6.6k установок/день на iOS); часть — не мёртвый worker (нет инъекции, медленный native). Перезапуск дешевле M4, но рвёт незавершённую работу background для других вкладок. Решить: включать сразу или через эксперимент.
|
||||
- [ ] **Телеметрия.** Восстановление после перезапуска сейчас попадает в `recovered_without_extension_reload` и неотличимо. Реализовать план из раздела «Телеметрия для валидации»; минимум — `network_replaced_since_view`, `native_seen` и пиксель `background_restarted`.
|
||||
- [ ] **Порядок выкатки.** Телеметрия раньше фиксов или вместе с ними в A/B-эксперименте с когортой в CPM-пикселях.
|
||||
- [ ] **Error 6 на iOS** (~1/3 строк `stuck`) не покрыт фиксами. Механизм воспроизведён на macOS (заморозка нового background ≥30 с во время загрузки). **Обновить iPhone до iOS 26.x** и подтвердить сценарий с будильником `cpm-summary` в фоне; затем решить про фикс.
|
||||
- [ ] **Error 6 на iOS** (~1/3 строк `stuck`) не покрыт фиксами. Причина найдена в WebKit (idle-таймер 30 с взводится до окончания загрузки), репро на macOS есть. На iPhone (iOS 26.7.1) в четырёх сценариях не воспроизвёлся. Выпустить телеметрию `bg_load_error_app_state` / `bg_load_error_after`, по данным выбрать фикс. Опционально: фоновый запуск системой с `sudo log collect` на Mac пользователя.
|
||||
- [ ] На тестовом iPhone стоит debug-сборка DDG вместо 7.221.0 — вернуть из App Store, когда тесты закончатся.
|
||||
- [ ] **Привязка вкладок на macOS:** гипотеза мигания флага отброшена; проверить popup-вкладки, кэш закреплённых вкладок и пересборку user scripts.
|
||||
- [ ] Телеметрия для error 6: причина в `context_errors` (описание ошибки, хотя бы категория) и состояние приложения в момент ошибки (foreground/background).
|
||||
- [x] Телеметрия для error 6: состояние приложения и задержка до ошибки — реализовано в `alex/cpm-web-extension-remaining-failures` (не закоммичено). Нужны privacy triage и решение, в каком PR выпускать.
|
||||
- [ ] **Остаток «здоровых» сбоев без смены Network-процесса** (1 170 iOS / 497 macOS) не объяснён; разделить после `native_seen`.
|
||||
- [ ] **SPI.** Перезапуск через `_killWebContentProcessAndResetState`, детекция через `_networkProcessIdentifier`; есть `responds(to:)`. Согласовать с командой (приложение уже использует SPI WebKit в этом месте).
|
||||
- [ ] **Сборка приложений.** iOS и macOS не собирал; изменения обратно совместимы (дефолтная реализация нового метода протокола, дефолтный параметр init). Проверить сборку и прогнать на iOS Simulator.
|
||||
|
||||
Reference in new issue
Block a user