본문 바로가기

일상

작업은 다 끝났는데 exit code 9로 죽는 faster-whisper (CUDA 종료 크래시 잡기)

반응형

로컬 GPU로 음성 전사를 돌리다가 좀 황당한 걸 만났습니다. 전사도 잘 되고 결과 텍스트도 멀쩡히 다 저장됐는데, 프로세스가 마지막에 exit code 9로 '실패'라고 뜨는 거였습니다. 결과물은 정상인데 종료만 비정상이라, 배치로 돌리면 자꾸 failed로 찍혀서 거슬렸습니다. 원인과 해결법을 정리합니다.


1. 증상: 결과는 정상인데 종료 코드만 9
faster-whisper로 전사가 다 끝나고 txt 저장까지 정상인데, 프로세스 종료 코드가 9로 찍힙니다. 백그라운드나 배치로 돌리면 성공인데도 '실패'로 표시돼서 거슬립니다.


- 전사와 파일 저장은 정상 완료
- 그런데 종료 코드가 9(비정상)
- 배치/백그라운드에서 성공인데도 failed로 보임


2. 진짜 원인은 '작업'이 아니라 '종료'
전사 로직 자체는 문제가 없습니다. 작업이 끝나고 파이썬이 종료되면서 GPU에 올린 모델과 CUDA 컨텍스트를 정리(teardown)하는데, 이 단계에서 네이티브 라이브러리(CTranslate2/CUDA)가 크래시가 납니다. 리소스 해제 순서/타이밍 문제라 결과물엔 영향이 없지만 종료 코드는 비정상(9)이 됩니다. 일은 다 하고 뒷정리하다 넘어진 셈입니다.


3. 해결: 뒷정리를 건너뛰고 즉시 정상 종료
모든 출력을 flush한 뒤 os._exit()로 종료 코드를 직접 지정하면 됩니다. os._exit()는 파이썬의 정상 종료 절차(atexit 핸들러, 객체 소멸자, 가비지 컬렉션)를 전부 건너뛰고 프로세스를 즉시 끝내기 때문에, 크래시가 나는 teardown 자체를 거치지 않습니다.



- main() 끝난 뒤 stdout/stderr를 flush
- os._exit(rc)로 정리 단계를 건너뛰고 즉시 종료
- 성공은 0, 예외는 1로 종료 코드 보존


4. 주의: os._exit는 정말 아무것도 안 치운다
os._exit()는 '즉시 종료'라서 정리를 하나도 안 합니다. 그래서 열어둔 파일이나 버퍼는 반드시 os._exit 전에 flush/close해야 합니다. 안 그러면 마지막 출력이 유실될 수 있습니다. 대신 위처럼 예외를 잡아 코드를 나눠두면 진짜 에러는 여전히 1로 잡힙니다.


- 열어둔 파일/버퍼는 os._exit 전에 flush와 close
- 로그 마지막 줄이 유실되지 않게 주의
- 예외 경로는 종료 코드 1로 구분


5. 정리
결과물은 멀쩡한데 종료 코드만 이상하면, 작업 로직이 아니라 '종료 경로'를 의심하는 게 빠릅니다. GPU 추론뿐 아니라 네이티브 확장을 쓰는 파이썬 프로세스에서 은근히 자주 나오는 패턴입니다. 배치 로그에 자꾸 failed가 떠서 스트레스라면 os._exit 한 줄로 끝낼 수 있습니다.


함께 보면 좋은 글:
- 패스터위스퍼(faster-whisper)로 한국어 음성을 텍스트로 (GPU 메모리 부족까지 잡기)


여기까지 작업은 다 끝났는데 exit code 9로 죽는 faster-whisper, CUDA 종료 크래시를 os._exit로 잡는 방법을 정리해봤습니다. 여기까지 읽어주셔서 감사합니다!

반응형