질문 역사:
Perl은 시스템 스크립트 언어로 개발되었으며, 따라서 신호 관리(SIGTERM, SIGINT, SIGHUP)는 항상 내장된 강력한 기능이었습니다. 이 시스템은 외부 이벤트(사용자 중지, 데몬 재시작, 타임아웃)를 가로채고 스크립트를 적절하게 종료하거나 동작을 변경할 수 있도록 합니다.
문제:
신호를 잘못 처리하는 것은 스크립트의 잘못된 종료나 중단, 데이터 손실, 상태나 자원을 잃지 않고 프로세스를 재시작할 수 없는 일반적인 원인입니다.
해결책:
신호는 특수 해시 %SIG에 핸들러를 설정하여 처리됩니다. 신호 핸들러 내부에서는 최소한의 작업(예: 플래그 설정 및 메인 스레드에서 안전하게 종료하는 작업)이 좋은 관행입니다. 스레드 내에서 올바르게 작동하고 다중 신호 처리를 위해서는 전문 모듈(POSIX::sigaction 등)을 사용하는 것이 좋습니다.
예:
my $term = 0; $SIG{TERM} = sub { $term = 1; }; while (1) { last if $term; # 주요 작업 } print "우아하게 종료되었습니다.\n";
주요 특징:
신호 핸들러 내에서 print/IO를 사용할 수 있습니까?
답변: 권장하지 않습니다. 잘못된 작업이 발생하며 데이터 손실이 있을 수 있습니다! 현대 표준은 최소 코드(플래그 설정/변수 정리만 수행)입니다.
첫 번째 실행 후 신호 핸들러를 재설정하지 않으면 어떻게 됩니까?
답변: 신호가 반복적으로 도착하는 경우 핸들러가 여러 번 작동합니다. 첫 번째 이벤트에만 반응이 필요하면 핸들러가 $SIG{...}를 스스로 재설정하거나 자신에게 신호를 보내야 합니다.
Perl에서 신호 처리가 스레드 안전합니까?
답변: 아닙니다! 멀티 스레드 Perl에서 신호 핸들러는 메인 스레드(주 해석기)에서만 호출되며, 스레드 내에서는 신호가 아예 누락되거나 잘못 처리될 수 있습니다.
SIGTERM을 받을 때 데몬 프로세스가 즉시 모든 파일 디스크립터를 닫고 임시 파일을 삭제하는 핸들러를 호출합니다 — 때때로 파일이 삭제되지 않으며 데이터가 손실됩니다.
장점:
단점:
SIGTERM 신호 핸들러는 단지 변수 $exit만 설정한 후, 메인 루프가 신중하게 작업을 종료하고 파일을 닫은 후 자원을 해제합니다.
장점:
단점: