-
Ghostty 터미널 에뮬레이터에서 장기간 실행 시 수십 GB의 메모리를 점유하는 심각한 누수 현상이 발견됨
- 문제의 원인은 PageList 구조체의 비표준 메모리 페이지 재사용 로직에서 munmap이 호출되지 않아 해제되지 않은 메모리가 누적된 것
-
Claude Code CLI가 다중 코드포인트 그래프 출력을 자주 생성하면서, 비표준 페이지 사용 빈도가 높아져 누수가 대규모로 드러남
- 수정은 비표준 페이지를 재사용하지 않고 즉시 해제하도록 변경되었으며, macOS의 VM 태그 기능을 활용해 누수 추적 및 검증이 이루어짐
- 이 수정은 Ghostty의 가장 큰 누수 문제 해결로 평가되며, 향후 릴리스(1.3)에 포함될 예정
Ghostty의 메모리 누수 개요
- 일부 사용자가 Ghostty가 장시간 실행 후 37GB 이상의 메모리를 사용하는 사례를 보고
- 누수는 최소 버전 1.0부터 존재했으며, 최근 CLI 앱들이 특정 조건을 충족해 문제를 노출
- 수정 사항은 이미 GitHub에 병합되었고, nightly 빌드 및 1.3 정식 릴리스에 포함 예정
PageList 구조와 메모리 관리 방식
- Ghostty는 터미널 내용을 저장하기 위해 PageList라는 이중 연결 리스트 구조를 사용
- 각 페이지는 문자, 스타일, 하이퍼링크 등의 데이터를 포함
- 페이지는 mmap으로 할당되며, 표준 크기 페이지 풀(pool) 을 통해 재사용
- 표준 크기 이하 페이지는 풀로 반환
-
비표준 크기 페이지는 직접 munmap으로 해제해야 함
- 이 구조 자체는 정상적이지만, 최적화 로직의 버그로 인해 누수가 발생
Scrollback 최적화와 버그 발생 원인
- Ghostty는 scrollback-limit을 초과하면 가장 오래된 페이지를 재사용하는 최적화를 수행
- 새 페이지 할당 없이 포인터만 조정해 성능 향상
- 문제는 이 과정에서 비표준 페이지의 메타데이터만 표준 크기로 변경하고 실제 메모리는 그대로 둔 점
- 이후 해제 시 표준 페이지로 오인되어 munmap이 호출되지 않음
- 이로 인해 비표준 페이지가 해제되지 않고 누적, 장기 실행 시 대규모 메모리 누수 발생
Claude Code와 누수의 대규모 노출
-
Claude Code CLI가 다중 코드포인트 그래프 출력을 자주 생성해 비표준 페이지 사용 빈도 증가
- 또한 스크롤백 출력이 많아 누수가 빠르게 누적
- Ghostty의 설계상 비표준 페이지는 드물게 발생해야 하지만, Claude Code의 특성으로 인해 누수가 대량으로 재현됨
- 개발자는 이 버그가 Claude Code의 문제가 아니라 Ghostty 내부 로직의 결함임을 명시
수정 내용
- 해결책은 비표준 페이지를 재사용하지 않고 즉시 해제(munmap) 하는 방식
- 스크롤백 중 비표준 페이지 발견 시 새 표준 페이지를 풀에서 재할당
- 일부 사용자는 비표준 페이지 재사용 전략을 제안했으나, 현재는 단순하고 안전한 수정이 우선 적용
- 수정 코드 예시:
if (first.data.memory.len > std_size) {
self.destroyNode(first);
break :prune;
}
VM 태그를 활용한 누수 추적
- macOS의 Mach 커널 VM 태그 기능을 사용해 PageList 메모리 할당에 특정 태그를 부여
- 디버깅 시 Ghostty의 메모리 영역을 명확히 식별 가능
- 누수 원인 추적 및 수정 검증에 큰 도움을 줌
- 이 기능으로 PageList 관련 메모리 해제 여부를 시각적으로 확인 가능
Ghostty의 메모리 누수 방지 체계
- Ghostty는 다양한 방식으로 누수를 탐지 및 방지
- 디버그 빌드와 단위 테스트에서 Zig의 누수 감지 할당자 사용
- CI에서 valgrind로 전체 테스트 수행
- macOS Instruments로 Swift 코드 누수 검사
- GTK 관련 PR은 Valgrind GUI 테스트로 검증
- 이번 누수는 특정 조건에서만 발생해 기존 테스트로는 재현되지 않았음
결론
- 이번 문제는 Ghostty에서 가장 큰 규모의 메모리 누수로 확인된 사례
- 수정 후에도 사용자 보고와 재현 테스트를 통해 지속적인 모니터링 예정
- 커뮤니티의 진단 데이터와 재현 사례 제공이 문제 해결에 결정적 역할
- 재현 가능한 환경 확보가 메모리 누수 해결의 핵심임을 강조