fix(pageout): SDK-константы, честный дефолт scratch, идентичность pid в recovery - #67
froggychips wants to merge 1 commit into
Conversation
…id identity in recovery (review 2026-09-19) Pageout.swift - kVMBehaviorPageout был 6 = VM_BEHAVIOR_FREE («free without write-back»): при удачном task_for_pid machVM уничтожал бы содержимое writable-страниц чужого процесса. Теперь символ SDK VM_BEHAVIOR_PAGEOUT (= 11, development only); VM_REGION_BASIC_INFO_64 тоже из SDK. - kMemorystatusCmdSetPriorityProperties был 1 = GET_PRIORITY_LIST; верное значение 2. При этом memorystatus_control требует root или entitlement com.apple.private.memorystatus (XNU kern_memorystatus.c) — jetsam для LaunchAgent недостижим, EPERM теперь объясняется словами. - MachVMPageoutImpl: 0 принятых регионов → .failed (раньше .success без единой страницы), цепочка откатывается дальше. - Дефолт PageoutChain.preferred → .scratch (ADR 0018). Doc-комментарии стратегий переписаны честно. FrozenPidsStore.swift / VortexActor.swift - Entry.startTime (proc_bsdinfo.pbi_start_tvsec) заполняется автоматически; recover() шлёт SIGCONT/SIGKILL только если pid жив, время старта (если записано) и путь бинаря совпадают — иначе «pid reused, skipping». recoverDetailed() отдаёт разбивку thawed/killed/skipped. Старые файлы без поля читаются. - clearFrozen(): thawAll снимает только записи приложений, записи воркеров переживают. - freezeProcess: журнал ДО SIGSTOP, при провале kill запись снимается; errno читается до await. Docs: ADR 0018 (en+ru) с фактами из SDK/XNU/baseline.json; ADR 0007 помечен частично superseded; индекс ADR дополнен 0016–0018; README (en+ru) — буллет про pageout и пример конфига переписаны под реальность. Tests: FrozenPidsStore — идентичность процесса (чужой startTime / чужой путь / полное совпадение / legacy JSON), clearFrozen; PageoutChain — дефолт scratch. Локально не компилировались (на машине нет XCTest). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wt32A3w8X6bMZAXKSVmsCv
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2ff522dc14
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| public init( | ||
| preferred: PageoutStrategy = .jetsam, | ||
| preferred: PageoutStrategy = .scratch, |
There was a problem hiding this comment.
Propagate the scratch default to FroggyConfig
The production daemon does not use this initializer default: Sources/FroggyDaemon/main.swift explicitly passes config.pageoutStrategy, while FroggyConfig() and its missing-field decoder fallback still default to .jetsam (Config.swift:121,226). Consequently, fresh or value-omitting configurations continue attempting the privileged jetsam strategy and incrementing its failure counters before falling back, contrary to the README and ADR changes in this commit; update the configuration default in the same change.
Useful? React with 👍 / 👎.
| guard thawGeneration == generationBefore else { | ||
| await pidStore?.remove(pid: pid) | ||
| throw VortexError.freezeAborted(pid: pid, reason: "thaw during freeze") |
There was a problem hiding this comment.
Recheck the thaw generation before reporting success
This guard only detects a thaw during pidStore.add; if thawAll or thawProcess runs after SIGSTOP while pageout.pageout or ranker.recordFreeze is awaited, it increments the generation, resumes and removes the PID, but freezeProcess later returns success. The awaiting VortexCoordinator.freezeTier then inserts that now-running PID into its frozen tier set after the thaw cleared the sets, causing subsequent pressure handling to skip it as already frozen. Recheck the captured generation before returning success so this overlap is reported as an aborted freeze.
Useful? React with 👍 / 👎.
Ревью 2026-09-19, поток «pageout». Факты — в новом ADR-0018.
Что не так было
Pageout.swift:278:kVMBehaviorPageout = 6— по SDK этоVM_BEHAVIOR_FREE(«free without write-back»). При удачномtask_for_pidmachVM стирал содержимое writable-страниц чужого процесса. НастоящийVM_BEHAVIOR_PAGEOUT= 11 и помечен «development only».Pageout.swift:272: команда1=GET_PRIORITY_LIST, а неSET_PRIORITY_PROPERTIES(= 2). И главное:memorystatus_controlтребует root илиcom.apple.private.memorystatus(XNUkern_memorystatus.c:9193) — стратегияjetsamдля LaunchAgent недостижима.bench/baseline.jsonэто и показывал:jetsamFailed: 1в каждом снимке.FrozenPidsStore.recover()бил SIGCONT/SIGKILL по pid без проверки, что это тот же процесс.VortexActor.freezeProcessписал журнал ПОСЛЕ SIGSTOP;thawAllсносил и записи живых воркеров.Что сделано
.failed, если ни один регион не принял behavior; jetsam при EPERM называет причину; дефолтPageoutChain→.scratch.FrozenPidsStore.Entry.startTime(proc_pidinfo) + проверка живости/пути/времени старта перед сигналом;clearFrozen()не трогает воркеров; legacy-файлы без поля читаются.VortexActor: журнал до SIGSTOP, откат при провале kill,thawGenerationзакрывает окно «add → thaw → SIGSTOP».Зависимость: дефолт
FroggyConfig.pageoutStrategy = .scratchживёт в #daemon-hardening (та же серия). До его мержа рабочий демон продолжит пробовать jetsam и падать в scratch — как и раньше.Проверка. Собрано локально (
swift build --product FroggyDaemon/froggy/FroggyAudioWorker, только CommandLineTools) без ошибок и предупреждений в изменённых файлах. Тесты не компилировались и не запускались: на машине нет XCTest (нет Xcode), self-hosted раннерjabbook-air-m3offline,ci.ymlна macos-latest давно startup_failure. Diff прошёл ревью Codex, замечания учтены. Перед мержем нуженmake testна машине с Xcode.🤖 Generated with Claude Code
https://claude.ai/code/session_01Wt32A3w8X6bMZAXKSVmsCv