PHP 4和5,Ctrl-C,system()和子进程
我有一个PHP脚本,它使用system()
调用来执行其他(可能长时间运行)程序(感兴趣的是:NCBI BLAST,phrap,primer3和其他用于进行DNA序列分析和组装的程序)。
我在Windows XP下运行,从命令提示符使用CLI的PHP版本,或者将其作为服务。 (无论哪种情况,我都通过数据库表中的任务队列与之通信)。
在PHP4下:当我按Ctrl + C时,脚本将停止,并且此时正在运行的所有子进程也将停止。
在PHP5下:当我按Ctrl + C时,脚本停止运行,但是孩子仍然在运行。
同样,将脚本作为服务运行时,用PHP4运行脚本时停止该服务会停止子进程,而使用PHP5则继续运行该子进程。
我尝试编写一个最小的测试应用程序,并发现了相同的行为。测试PHP脚本仅使用system()执行一个C程序(该程序仅睡眠30秒),然后等待按键被按下。
我查看了PHP 4.4.9和5.2.6的源代码,但看不到看起来像它们会导致此问题的system()代码中的差异。我还快速浏览了CLI应用程序的启动代码,但在信号处理方面没有发现任何差异。
任何可能导致此问题的提示或者解决方法,将不胜感激。
谢谢。
解决方案
至少在PHP 5.1.2中会发生此问题。
通过CTRL + C或者CTRL + BREAK发送SIGINT时,将调用处理程序。如果此处理程序将SIGTERM发送给其他子级,则不会接收到信号。
SIGINT可以通过posix_kill()发送,并且完全按预期工作-仅在通过硬中断启动时才适用。
来自:http://php.oregonstate.edu/manual/zh/function.pcntl-signal.php
该文档包含用于捕获CTRL + C并将posix_kill发送给孩子的示例代码。
它还包含许多其他关于子代步和信号的代码和信息。
而不是使用system(),请查看proc_open(),proc_close()和proc_terminate()。