OSSCA Chromium

기여 목록 / 8424764

CacheStorage: Reject operations once cache closing starts

ContentfixMerged

CacheStorage 캐시가 닫히기 시작한 뒤 들어온 작업을 즉시 거절하도록 변경했습니다. 닫기 전에 예약된 작업은 그대로 완료하고, 닫기 콜백이 캐시를 삭제하더라도 이후 요청의 콜백이 사라지지 않게 했습니다.

문제 설명

CacheStorageCache::Close()와 GetSizeThenClose()는 닫기 작업을 스케줄러에 배타적으로 예약합니다. 실제 백엔드가 닫히기 전까지는 backend_state_가 열려 있으므로, 이 사이에 들어온 새 요청이 닫기 작업 뒤에 예약될 수 있었습니다.

닫기 콜백에서 캐시 객체를 삭제하면 그 뒤에 대기하던 작업도 사라져 호출자가 응답 콜백을 받지 못합니다. 반대로 닫기 요청 전에 이미 예약한 작업은 백엔드가 열려 있는 동안 정상적으로 끝나야 하므로, 단순히 백엔드 상태를 미리 BACKEND_CLOSED로 바꿀 수도 없습니다.

해결 내용

  1. cache_storage_cache.h에 close_requested_와 IsClosingOrClosed()를 추가했습니다. Close()와 GetSizeThenClose()가 호출되면 닫기 작업을 예약하기 전에 플래그를 설정합니다. 백엔드 상태는 실제 닫기 작업이 실행될 때까지 유지합니다.
  2. Match(), MatchAll(), Keys(), Put(), BatchOperation(), WriteSideData() 등 새 요청의 진입점에서 닫는 중인 캐시를 기존의 백엔드 종료 오류 경로로 거절합니다. Size()와 중복 GetSizeThenClose()는 기존 종료 상태와 같이 크기 0을 반환합니다.
  3. 할당량 조회가 비동기로 끝나는 배치·side data 경로에서도 닫기 상태를 다시 검사합니다. 조회가 시작된 뒤 캐시 닫기가 요청돼도 뒤늦게 새 작업을 예약하지 않습니다.

닫기 전에 스케줄러에 들어간 작업은 계속 실행됩니다. 새 요청만 조기에 완료시키므로 닫기 콜백에서 캐시를 삭제해도 대기 중인 새 요청의 콜백이 유실되지 않습니다.

테스트 방법

cache_storage_cache_unittest.cc에 스케줄러를 의도적으로 막아 닫기 요청과 실제 종료 사이를 재현하는 회귀 테스트를 추가했습니다. 메모리·디스크 캐시 설정에서 다음을 확인합니다.

테스트 검증 내용
OpsFailWhileCloseIsPending Close() 이후의 새 요청은 닫기 전에 오류 콜백을 받고, 닫기 전에 예약한 작업은 정상 완료합니다.
OpsFailWhileGetSizeThenCloseIsPending GetSizeThenClose()에서도 같은 요청 차단과 기존 작업 완료를 확인합니다.
QuotaCallbacksFailWhileCloseIsPending 배치와 side data의 할당량 조회가 닫기 중에 완료돼도 오류 콜백을 돌려줍니다.

패치 설명에는 집중 실행한 CacheStorageCache, CacheStorageManager, CacheStorageScheduler 테스트 344개가 통과했다고 기록돼 있습니다. 보고서 작성 과정에서 Chromium 테스트를 별도로 실행하지는 않았습니다.

배운 점

  • 닫기 작업을 큐에 넣는 순간과 백엔드가 실제로 닫히는 순간은 다릅니다. 새 작업을 차단하려면 이 중간 상태를 별도로 표현해야 합니다.
  • 닫기 요청 전에 예약된 작업과 이후 요청을 구분하면 기존 작업을 안전하게 마치면서 콜백 유실을 막을 수 있습니다.
  • 비동기 할당량 조회처럼 요청 진입 후 다시 스케줄러에 들어가는 경로는 완료 시점에도 닫기 상태를 확인해야 합니다.

참고 자료