Watch at Ease세상을 읽고, 일상의 답을 찾다.

기술 · 실용 가이드

Python resource_tracker leaked shared_memory: 수명 소유자를 하나로 정하세요

track을 바꾸기 전에 생성자, 연결자와 tracker 계보를 그립니다. 한 프로세스만 unlink를 소유하게 하고 생존과 정리를 모두 테스트합니다.

Original diagram mapping a shared-memory creator, attachers, tracker family and one unlink owner.
원본 일러스트: track을 바꾸기 전에 shared-memory 수명 소유자를 하나로 정합니다. Watch at Ease

resource_tracker 경고는 close() 누락만 뜻하지 않습니다. 독립 Python 프로세스 계보가 같은 POSIX shared-memory 이름을 각각 소유한다고 생각하면 먼저 끝난 tracker가 사용 중인 이름을 일찍 제거할 수 있습니다.

수정은 소유권 결정입니다. Python 버전, 플랫폼, 실행 계보, 생성자, 연결자와 종료 순서를 기록하고 이름마다 unlink 소유자를 하나만 지정한 뒤 track을 선택합니다.

프로세스 계보 고정

OS, Python 버전, start method, service manager, 생성자 PID, 연결자 PID, 실행 방법과 종료 순서를 기록합니다. 별도 terminal, subprocess tree, container와 uWSGI worker는 다른 tracker 계보일 수 있습니다.

정확한 이름, create, track과 모든 close/unlink 호출을 기록합니다. 원래 경고와 이후 attach 결과를 보존합니다.

handle, mapping, 이름 수명 분리

close()는 이 객체의 접근을 끝냅니다. POSIX unlink()는 이름을 제거하며 기존 mapping과 최종 회수는 플랫폼 규칙을 따릅니다. 로컬 close만으로 이름 생존이나 정리 소유자를 증명할 수 없습니다.

이름마다 생성자, 활성 연결자, tracker 계보, 지속 소유자, close 책임과 단 하나의 unlink 책임을 표로 만듭니다.

track 전에 소유자 모델 선택

하나의 multiprocessing 계보에서는 공유 tracker가 비정상 종료 정리를 담당할 수 있지만 모든 handle close와 정상 unlink 경로 하나는 여전히 필요합니다. 각 worker가 unlink하면 안 됩니다.

독립 또는 타 언어 프로세스에서는 소비자보다 오래 사는 coordinator를 고릅니다. Python 3.13+ 비소유 연결자는 다른 주체가 정리를 맡을 때만 track=False를 씁니다.

버전과 플랫폼 분기 유지

Python 3.13 이전에는 공개 track이 없습니다. private unregister나 monkey patch를 일반적인 production 수정으로 쓰지 말고 upgrade, 계보 통합 또는 명시적 coordinator를 선택합니다.

Windows는 track을 무시하고 POSIX 이름은 unlink와 마지막 unmap까지 남을 수 있으므로 플랫폼별 acceptance가 필요합니다.

양방향 종료 테스트

owner와 두 non-owner를 시작해 generation marker를 쓰고 한 non-owner를 중지합니다. 새 attacher가 같은 이름과 marker를 읽어야 합니다.

남은 non-owner와 마지막 owner를 중지하고 한 번의 unlink 뒤 새 attach가 실패해야 합니다. abnormal exit는 disposable fixture에서 별도 시험합니다.

Original decision diagram requiring shared-memory survival after a non-owner exits and cleanup after the owner exits.
원본 일러스트: 종료 테스트는 생존과 최종 정리를 모두 확인합니다. Watch at Ease