PHP에서 pcntl_signal()을 사용하여 시그널을 핸들링 하려면 declare(ticks=1) 선언이 필요하다.
또는 PHP 7.1부터 pcntl_async_signals(true)을 사용하는 것으로 대신할 수 있다.
그런데 SIGINT 시그널이 발생하여 핸들링을 하는 경우 declare(ticks=1)를 쓸 때와 pcntl_async_signals(true)를 쓸 때 각각의 register_shutdown_function()에 등록한 핸들러의 호출 여부가 달라진다. (PHP 7.4에서 테스트)
- declare(ticks=1)
- register_shutdown_function()에 등록한 핸들러가 호출되지 않는다.
- pcntl_async_signals(true)
- register_shutdown_function()에 등록한 핸들러가 호출된다.
부모 프로세스에서 pcntl_fork()로 나온 자식 프로세스에서 exec()로 또 다른 PHP 스크립트를 실행하는 과정에서 인터럽트에 의한 종료에서도 가능한 정상적인 종료에서와 같은 종료 로직을 거치게 하려고 테스트 하는 과정에서 발견했다.
위 내용이 어렵고 무슨 이야기인지 모른다고 해서 심각하게 들여다 볼 필요는 없다. 단순히 register_shutdown_function()에 등록한 핸들러에 실행 여부를 체크하는 변수 한개만으로 중복 실행만 막으면 된다. 나는 단지 궁금해서 다양한 사례로 테스트를 해본 것이고 그 결과를 기록하는 것 뿐이다. 또한 이 결과는 PHP 버전이 바뀌면 달라질 수도 있다.
정리하면 상황에 따라 register_shutdown_function()에 등록한 핸들러가 중복 실행이 될 수 있으므로 중복 실행이 되지 않도록 방어적인 코딩을 하면 좋을 것 같다.