[prefs] Remove expired NotFatalUntil::M143 from PrefService type checks
PrefService의 pref 타입 검사 네 곳에 붙어 있던 base::NotFatalUntil::M143 인자를 제거하고, base/not_fatal_until.h의 마일스톤 목록에서도 M143 항목을 지웠습니다(crbug.com/438680281). 단계적 CHECK 롤아웃이 12개 마일스톤 전에 끝났는데 그 흔적만 남아 있던 경우로, 헤더 주석이 직접 지시하는 뒷정리 작업입니다. 2026-09-14에 머지됐습니다(fdce3e159a88b).
문제 설명
- issue url: https://crbug.com/438680281
- Chromium에는 새
CHECK를 단계적으로 켜는 장치가 있습니다.CHECK(cond, base::NotFatalUntil::M143)은 M143 전까지 프로세스를 죽이지 않고 덤프만 남기고, M143부터 fatal이 됩니다. 그동안 크래시 리포트를 모아 "이 CHECK를 켜도 되는지" 확인하라는 뜻입니다(base/check.h). - 2025-08-28 CL 6845990이 pref 등록 타입과 접근 타입이 일치하는지 검사하는
CHECK_EQ를PrefService::SetInt64()/GetInt64()/SetTime()/GetTime()네 곳에 추가하면서, 롤아웃 장치로NotFatalUntil::M143을 함께 붙였습니다. - 판정 로직(base/check.cc)은 지정 마일스톤이 현재 마일스톤 이하이면 그냥
LOGGING_FATAL입니다. 현재chrome/VERSION의 MAJOR는 155이므로 143 ≤ 155, 즉 이 네 개 CHECK는 이미 12개 마일스톤째 fatal이며 인자는 아무 효과 없이 남아 있었습니다. - 정리 방법은 헤더 자신이 지시하고 있습니다(base/not_fatal_until.h):
To clean up old entries remove the already-fatal argument from CHECKs as well as from this list. This generates better-optimized CHECKs in official builds.
해결 내용
components/prefs/pref_service.cc의 네CHECK_EQ에서 세 번째 인자만 제거했습니다. 조건식과<< path스트림은 그대로 두었습니다.base/not_fatal_until.h의 enum에서M143 = 143,한 줄을 삭제해 마일스톤 M143을 트리에서 완전히 없앴습니다.
void PrefService::SetInt64(std::string_view path, int64_t value) {
CHECK_EQ(pref_registry_->GetRegisteredPrefType(path).value_or(
PrefRegistry::RegisteredPrefType::kInt64),
- PrefRegistry::RegisteredPrefType::kInt64, base::NotFatalUntil::M143)
+ PrefRegistry::RegisteredPrefType::kInt64)
<< path;인자만 빼고 enum 항목을 남기면 정리가 절반만 된 상태가 됩니다. 헤더가 "CHECK에서도, 이 목록에서도" 지우라고 명시한 이유이기도 하고, 그래야 다음 사람이 목록을 볼 때 남아 있는 마일스톤이 전부 유효한 것이 됩니다.
동작 변화: 크래시 여부는 달라지지 않습니다. 이미 fatal이었고 앞으로도 fatal입니다. 바뀌는 것은 코드 생성으로, 인자가 없으면 공식 빌드에서 CHECK가 로그 문자열을 버립니다(base/check.h). 바이너리가 작아지는 대신 이 CHECK가 실패했을 때 크래시 리포트에 pref 경로가 실리지 않으므로, 이 트레이드오프를 CL 설명에 명시했습니다.
enum 항목 삭제가 안전한 근거는 두 가지입니다. NotFatalUntil::M143 참조가 트리 전체에서 위 네 곳뿐이었고, base/check.cc는 이 enum을 std::to_underlying으로 수치 비교만 할 뿐 값을 열거하거나 switch 하지 않습니다.
발굴 과정
코드에서 출발해 이슈로 거슬러 올라간 경우입니다.
- 만료된
NotFatalUntil(현재 MAJOR 미만) 사용처를components/,net/,services/에서 수집해 61곳을 찾았습니다. - 그대로 하나씩 지우면 여러 OWNER 그룹에 걸쳐 승인 수집이 병목이 되므로, 마일스톤 단위로 전 트리를 다시 집계해 "그 마일스톤이 단 한 파일에만 남아 있는" 경우를 찾았습니다. 그래야 CL 하나로 인자 제거와 enum 항목 삭제를 함께 끝낼 수 있습니다.
- 세 개가 나왔고(M143 / M146 / M147), 그중 이슈가 미할당·375일 무활동이고 파일이 하나인 M143을 골랐습니다.
테스트 방법
런타임 동작이 바뀌지 않는 정리 작업이라 새 회귀 테스트를 추가하지 않았고, 기존 테스트 전원 통과와 컴파일이 검증입니다.
base/not_fatal_until.h는base/check.h가 include하고,check.h를 직접 include하는 파일만 5,179개입니다. 따라서 헤더 한 줄 수정에도 사실상 전 트리가 다시 빌드됩니다 —Build Succeeded까지 33,412스텝 / 13시간 23분이 걸렸습니다.components_unittests --gtest_filter='PrefService*'47/47 통과base_unittests --gtest_filter='CheckTest.*:CheckDeathTest.*'26/26 통과 — enum 항목 삭제를 직접 검증하기 위해 이 타깃을 함께 빌드했습니다.
업로드 시 presubmit이 "Discovered possible removal of preference registrations" 경고를 띄웠는데, 삭제된 줄에 PrefRegistry::RegisteredPrefType::kInt64가 포함되어 발생한 오탐입니다. pref 등록이 아니라 CHECK_EQ의 인자를 제거한 것이며, 경고문 자체도 false positive 가능성을 명시하고 있습니다.
배운 점
base/아래 헤더는 한 줄만 고쳐도 전 트리 재빌드입니다. 변경 크기(+4/−5, 2파일)와 검증 비용(13시간)이 전혀 비례하지 않으므로, 착수 전에check.h처럼 널리 include되는 헤더를 건드리는지 확인하는 편이 좋습니다.- 이슈가
Fixed로 닫혔거나 조용하다고 해서 작업이 끝난 것은 아닙니다. 이 경우는 반대로 이슈가 열려 있었지만, 정리 지시는 이슈가 아니라 헤더 주석에 적혀 있었습니다. 코드에서 출발하는 발굴 경로가 트래커 검색으로는 안 보이는 작업을 찾아줍니다.