我正在运行一个带有信号处理程序的PHP守护程序来进行有序清理并重新配置而不停止:
declare(ticks = 5);
function sig_handler($signo)
{
...
}
pcntl_signal(SIGHUP, 'sig_handler');
pcntl_signal(SIGINT, 'sig_handler');
...
A tick是由声明块中的解析器执行的每N个低级别可勾选语句发生的事件...并非所有语句都是可勾选的。通常,条件表达式和参数表达式不可勾选。
如果我们声明ticks = 1
,那么将在执行PHP代码的大多数行之间检查信号,这似乎是低效的。所以,
ticks = 5
,这是否意味着我们有四分之五的机会信号处理程序根本不会被调用?(旁注:The formal specs甚至更不具体,因为这可能是依赖于解释器的。)
答案 0 :(得分:5)
以下是我的调查结果,我无法提供任何文件证明我的陈述。但是,我通过阅读PHP的源代码(pcntl
extension)了解了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扩展中。
在您的情况下,您可能需要阻止SIGHUP
(这是通常发送给后台程序以使其重新加载其配置的信号)。