문제 발생

파일 핸들 누수 문제가 나타난 입력, 직전 동작과 실제 결과를 함께 적습니다. 예를 들어 “가끔 실패”라고 쓰는 대신 정상 사례와 실패 사례를 하나씩 두고, 두 사례에서 달라진 version·설정·데이터를 표로 남깁니다.

사례 입력과 상태 결과
정상 가장 작은 정상 조건 기대한 결과
실패 한 조건만 달라진 재현 실제 오류·값

원인 분석

file object를 명시적으로 닫지 않고 GC 시점에 기대면 descriptor가 늦게 반환될 수 있어 with context manager를 사용해야 합니다.

heap 사용량과 열린 file·socket·timer·listener를 분리합니다. 작업이 끝난 뒤에도 handle 수가 기준선으로 돌아오지 않는지 확인합니다. py-spy/cProfile, tracemalloc, gc 통계, RSS, task와 file descriptor를 재현 입력과 함께 측정한다. 정상과 실패를 번갈아 실행하고, 이 원인이 맞다면 달라져야 할 값부터 확인합니다. 관련 없는 로그와 설정을 한꺼번에 바꾸지 않습니다.

해결 방안

자원을 만든 코드가 성공·실패·취소 경로 모두에서 닫도록 수명주기를 한곳에 둡니다. timeout과 finally·cleanup을 짝으로 관리합니다. CPU와 I/O 작업을 구분하고 iterator, context manager, timeout, process·thread 선택을 측정 결과로 결정한다.

수정 전 실패 사례가 사라지고 기존 정상 사례가 유지돼야 합니다. 입력 크기별 시간·메모리 복잡도, 장시간 RSS 기준선, 열린 자원과 취소 후 task를 확인한다. 정상 완료, 중간 오류와 취소를 반복한 뒤 열린 handle·descriptor·task 수가 기준선으로 돌아오고 다음 작업이 정상 실행되는지 확인합니다. 가장 작은 실패 입력은 자동 테스트나 실행 가능한 점검 명령으로 남깁니다.

공식 문서와 적용 범위

문서의 기본값과 동작은 version에 따라 달라질 수 있습니다. 현재 Python 구현과 version, dependency, 입력 크기와 실행 환경에서 다시 확인합니다.