我正在运行一个带有信号处理程序的PHP守护程序来进行有序清理并重新配置而不停止:
declare(ticks = 5);
function sig_handler($signo)
{
...
}
pcntl_signal(SIGHUP, 'sig_handler');
pcntl_signal(SIGINT, 'sig_handler');
...
Run Code Online (Sandbox Code Playgroud)
tick是由声明块中的解析器执行的每N个低级别可勾选语句发生的事件...并非所有语句都是可勾选的.通常,条件表达式和参数表达式不可选.
如果我们声明ticks = 1那么将在执行PHP代码的大多数行之间检查信号,这似乎是低效的.所以,
ticks = 5,这是否意味着我们有五分之一的机会信号处理程序根本不会被调用?(旁注:正式规范甚至不那么具体,因为这可能是依赖于解释器的.)
以下是我的调查结果,我不能为您提供任何文件证明我的陈述.但是,我通过阅读PHP的源代码(pcntl扩展)了解了PHP解释器处理滴答和信号的方式.
- 如果我们设置
ticks = 5,这是否意味着我们有四分之一的机会信号处理程序根本不会被调用?
PHP是一种解释型语言.操作系统不会调用您的PHP信号处理程序来处理信号.解释器向OS注册信号处理程序,并将收到的所有信号放入队列中.
OS信号是异步的.解释器将信号发送给您定义的处理程序,当它是最合适的时间时.这发生在低级别可选语句之间.
declare(ticks = 5);使信号调度程序每5个可选择的语句运行一次.在两次呼叫调度员期间到达的信号不会丢失; 它们被添加到队列中并在下次调用时处理.
信号调度员的代码很轻; 这不是一个很大的开销declare(ticks = 1).
- 如何确定一致但有效的设置?
这取决于你的程序做什么.没有配方.尝试不同的设置,选择最适合您的设置.
- 阻塞调用期间会发生什么,例如数据库查询?信号在返回时是丢弃还是被处理?
如上所述,信号由解释器安装的信号处理程序异步处理.处理仅将信号放入队列中.它们是从队列中挑选出来的,当它是解释器最合适的时刻(以及你的PHP代码)时,它们会被分派到你的代码中.什么都没有丢失.
关于数据库,我只检查过(几年前)mysql.我的代码pcntl_fork()用于创建工作进程,并正在处理SIGCHLD以跟踪工作人员的活动.出于神秘的原因,它经常在MySQL查询失败时显示消息"连接丢失"而没有任何明显的原因.在经过大量调查和阅读大量文档之后,我发现信号使得sleep()家庭中的函数提前返回,这使得mysql客户端库的代码认为连接丢失了.
解决方案非常简单.我曾经在运行MySQL查询之前pcntl_sigprocmask()阻塞SIGCHLD信号,并在查询完成后立即取消阻止.我对其他信号不感兴趣.让他们来,将导致流程终止; 无论如何,当程序即将退出时,为什么还要打扰MySQL查询失败呢?
我不知道如果信号影响的操作mysqli或者PDO,但我认为他们这样做.在我的情况下受影响的操作是MySQL客户端和服务器之间的低级通信的一部分,深入libmysql到PHP扩展中而不是在PHP扩展中.
在您的情况下,您可能需要阻塞SIGHUP(这是通常发送给守护进程以使其重新加载其配置的信号).