PHP pcntl_async_signals
和 pcntl_wait
信号处理兼容性详解
本文分析PHP进程管理中pcntl_async_signals
函数与pcntl_wait
函数的信号处理兼容性问题。 一个PHP程序启用pcntl_async_signals(true)
进行异步信号处理,父进程同时使用while
循环和pcntl_wait
阻塞,结果发现只有while
循环能正确接收并处理SIGTERM信号,pcntl_wait
却无法触发信号回调。
代码示例中,Server
类模拟了父进程和子进程的结构。父进程用pcntl_fork
创建子进程,并通过pcntl_signal
注册SIGTERM信号的处理函数masterTermHandler
。start
方法中,父进程先启用pcntl_async_signals(true)
,然后分别用while
循环(配合usleep
)和pcntl_wait
阻塞父进程。
问题在于,使用pcntl_wait
阻塞时,masterTermHandler
不会被调用,而while
循环则正常工作。 这并非pcntl_async_signals
和pcntl_wait
本身冲突,而是pcntl_signal
函数的第三个参数设置导致的。
pcntl_signal
的第三个参数默认为true
,表示信号处理函数不会中断当前阻塞操作。 while
循环中,usleep
定期释放CPU,允许PHP解释器处理信号并调用信号处理函数。但pcntl_wait
是阻塞函数,它持续等待子进程结束,即使收到信号,也不会中断pcntl_wait
,导致信号处理函数无法执行。
解决方法是将pcntl_signal
的第三个参数设置为false
,强制信号处理函数立即执行,即使当前处于阻塞状态。 这样,即使pcntl_wait
阻塞,收到SIGTERM信号时,信号处理函数也会被调用,从而正确处理信号。 因此,pcntl_async_signals
和pcntl_wait
本身并非不兼容,关键在于正确设置pcntl_signal
函数的参数。