0

我有一个自定义 php 脚本,它使用 proc_open 打开第三方 perl 脚本。我试图放入一些 pcntl_signal 句柄,以便我可以在中断时优雅地清理。

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

但是,当它通过带有 proc_open 的子脚本循环时,CTRL+C 似乎就完全死在那里了。需要明确的是,我的意思是立即完全停止父进程和子进程。并不是说 ctrl+c 被第 3 方子进程捕获,返回并且我的脚本继续。

我在 php 文档中读过,已知信号处理不能很好地与 sleep() 之类的东西配合使用,并认为它可能与 POSIX proc_open 函数类似。仔细查看 SO,似乎有一些类似的帖子提供了一种解决方案,可以根据情况在子进程中移动信号处理或将 restart_syscalls 参数切换为 proc_open。

我尝试将restart_syscalls 参数切换为false,但这对我没有任何好处。

不幸的是,子进程是第 3 方脚本,所以我不熟悉实际代码。在试图解决这个问题以使信号重新传播之前(如果可能的话,甚至是要做的事情),我想知道我的设置是否缺少一些东西,所以我可以只维护我的代码。

我所拥有的看起来像

<?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']);
4

1 回答 1

0

You should listen to SIGCHLD too, if you want to be notified when your child dies. I think that you can also put safely for example sleep(1) inside the polling cycle to reduce busy work.

于 2013-02-14T02:50:09.160 回答