php pcntl_signal与proc_open

时间:2013-02-14 00:54:59

标签: php signals

我有一个自定义的PHP脚本,使用proc_open打开第三方perl脚本。我试图放入一些pcntl_signal句柄,这样我就可以在中断时优雅地进行清理。

我能让我的信号处理程序在更狭窄的测试床上工作,它只是在一个循环或其他东西中旋转。

然而,当它循环遍历子脚本w / proc_open时,CTRL + C似乎完全就在那里死了。要明确我的意思是完全立即停止父子进程。它是,好像ctrl + c被第三方子进程捕获,返回并且我的脚本继续。

我已经在php文档中读到了它已知的信号处理与sleep()之类的东西不能很好地兼容并且认为它可能与POSIX proc_open函数类似。看看SO似乎有一些类似的帖子,可以解决在子进程中移动信号处理或将restart_syscalls参数切换到proc_open,具体取决于具体情况。

我尝试将restart_syscalls param切换为false,但这对我没有任何帮助。

不幸的是,子进程是第三方脚本,所以我不熟悉实际的代码。在试图将信号传播回去之前(如果可能或甚至要做的事情)我想知道我的设置是否缺少某些东西,所以我只能维护我的代码。

我的样子

<?php

declare(ticks=1);

class signalHandler{

    public static function handle($signal){
        throw new KillException("Received Kill signal $signal", $signal);
    }

}
pcntl_signal(SIGINT,array('signalHandler','handle'));

然后,调用实际的子进程:

$childCmd = "thirdPartyScript.pl";

// Set up how we'll interact with the IO file handlers of the process
$descriptors = Array(
    0 => Array('file', '/dev/null', 'r'), // Process will read from /dev/null
    1 => Array('pipe', 'w'), // Process will write to STDOUT pipe
    2 => Array('pipe', 'w')  // Process will write to STDERR pipe
);

// Start the process
$childProc = proc_open($childCmd, $descriptors, $pipes);

// Check the status of the backup every second...
$streamContents = '';

stream_set_blocking($pipes[2], 0);
do {
    $streamContents .= stream_get_contents($pipes[2]);

    if( ! ( $childStatus = proc_get_status($childProc) ) ) {
        throw new Exception("Error: Unable to retrieve status on child process.");
    }


} while ($childStatus['running']);

1 个答案:

答案 0 :(得分:0)

如果您希望在孩子死亡时收到通知,您也应该听SIGCHLD。 我认为您也可以安全地放置在轮询周期内的sleep(1),以减少繁忙的工作。