← All reports

Move memory-footprint sampling to a UIProcess `MemoryFootprintMonitor`

Component: WebKit UIProcess | 8009ddd

WebKit은 page 단위로 foreground/background 메모리 한계를 적용합니다. OS가 애플리케이션 전체를 OOM kill하기 전에 먼저 해당 process를 종료하기 위한 장치입니다. 기존 구현에서는 sandbox 안의 각 WebProcess가 30초마다 task_info(mach_task_self(), ...)로 자신의 phys_footprint를 측정하고, 그 값을 한계 적용용으로 보고했습니다. 문제는 iOS의 app sandbox가 호출자 자신 외의 pid에 대해서는 task_name_for_pid를 차단한다는 점입니다. 그래서 UIProcess가 WebProcess의 task name port를 직접 얻어낼 수는 없습니다.

이번 commit은 샘플링 위치를 UIProcess 쪽의 새로운 MemoryFootprintMonitor로 옮깁니다. 이 monitor는 suspend되지 않은 모든 WebContent process를 직접 측정합니다. iOS에서 이 방식이 동작하도록, WebProcess는 자신의 task_name_port를 UIProcess로 전달합니다. 해당 port는 제한된 Mach port 변형으로, 일부 task_info flavor만 허용하며 메모리 read/write나 thread 제어는 허용하지 않습니다. 전달 경로는 WebProcessProxy에 새로 추가된 setTaskNamePort IPC 메시지입니다. 이후 UIProcess가 그 port를 대상으로 직접 task_info를 호출합니다.

메모리 한계 적용이 더 이상 sandbox 안의 renderer가 자기 자신에 대해 보고한 수치에 의존하지 않습니다. 주된 동기는 Site Isolation입니다. 하나의 page가 여러 WebProcess에 걸쳐 존재하게 되면, process별 self-sampling만으로는 page 단위 한계를 정확히 적용할 수 없습니다. 보안 측면의 부수 효과는 따로 있습니다. process 종료 판단에서 renderer가 제어하는 데이터 출처 하나가 제거된다는 점입니다.

여기서 눈여겨볼 패턴은 신뢰 수준이 더 높은 process가 sandbox 안의 process로부터 올라온 Mach port를 받아들인다는 점입니다. 좁게 보면, WebContent로부터 port right나 send right를 받는 다른 WebProcessProxy 메시지 handler들을 점검해 볼 수 있습니다. 수신 측이 port의 종류에 대해 무엇을 가정하는지, 그리고 그 가정이 깨졌을 때 어떻게 동작하는지를 확인하면 됩니다. 더 넓은 범주는 sandbox process가 스스로 보고한 값을 받아 판단하는 enforcement 결정 전반입니다. process 종료, jetsam, throttling 정책에 들어가는 나머지 입력들을 나열해 보고, 각각이 UIProcess가 측정한 값인지 renderer가 주장한 값인지를 구분해 볼 필요가 있습니다. 가장 넓게 보면, 권한이 비대칭인 상황에서 측정 대상이 측정값까지 직접 제공하는 모든 구도가 같은 모양입니다. 오래 가는 해법은 신뢰 측이 handle을 확보해 직접 측정하는 쪽이며, 이번 task_name_port 전달이 바로 그 역할을 합니다. 코드 리뷰에서의 신호는 이렇습니다. 파라미터가 값 타입이 아니라 port나 handle 타입인 IPC 메시지가, 발신 측보다 권한이 높은 process에 도착하는 경우입니다.