PHP的sleep、pcntl_signal和ticks函数

5

好的,我一直在尝试让 Process SignalsPHP 脚本一起工作。我遇到了很多问题,有些情况下我不确定发生了什么,而且我觉得文档并没有很好地解释清楚。

所以假设我按照 注册信号 的示例进行操作:

<?php
// tick use required as of PHP 4.3.0
declare(ticks = 1);

// signal handler function
function sig_handler($signo)
{

     switch ($signo) {
         case SIGTERM:
             // handle shutdown tasks
             exit;
             break;
         case SIGHUP:
             // handle restart tasks
             break;
         case SIGUSR1:
             echo "Caught SIGUSR1...\n";
             break;
         default:
             // handle all other signals
     }

}

echo "Installing signal handler...\n";

// setup signal handlers
pcntl_signal(SIGTERM, "sig_handler");
pcntl_signal(SIGHUP,  "sig_handler");
pcntl_signal(SIGUSR1, "sig_handler");

// or use an object, available as of PHP 4.3.0
// pcntl_signal(SIGUSR1, array($obj, "do_something"));

echo"Generating signal SIGTERM to self...\n";

// send SIGUSR1 to current process id
posix_kill(posix_getpid(), SIGUSR1);

echo "Done\n";

?>

然而,在我的 sig_handler 函数中,我在结尾处添加了一个 exit(1)。那么 echo "Done\n"; 仍然会执行吗?我尝试过类似的操作,虽然是在类结构中,但只有在我的 sig_handler 被调用之前才能实现。
我的类 __construct 调用函数 registerSignals:
private function registerSignals(){
    if(function_exists("pcntl_signal")){
        //call_user_func([$this, "sigintCleanup"]);
        pcntl_signal(SIGINT, [$this, "sigintCleanup"]);
        pcntl_signal(SIGTERM, [$this, "sigtermCleanup"]);
        pcntl_signal(SIGHUP, [$this, "sighupCleanup"]);
        pcntl_signal(SIGUSR1, [$this, "sigusr1Cleanup"]);
    }
}

protected function sigintCleanup(){
    echo "In SIGINT cleanup\n";
    $this->cleanup();
}

protected function sigtermCleanup(){
    echo "In SIGTERM cleanup\n";
    $this->cleanup();
}

protected function sighupCleanup(){
    echo "In SIGHUP cleanup\n";
    $this->cleanup();
}

protected function sigusr1Cleanup(){
    echo "In SIGUSR1 cleanup\n";
    $this->cleanup();
}

protected function cleanup(){
    echo "Shutting down\n";
    exit(1);
}

在测试这个过程中,我会进行一些简单的sleepecho操作(start只是在构建和信号注册完成后调用的一个函数):

function start(){
    echo "-- Testing the test script --\n";
    sleep(10000);
    echo "given how ticks work, this might not be called...\n";
    echo "\nAfter sleep... this should not be executed if there was a signal interrupt.\n";
}

所以我在 sleep 过程中使用 ctl-c。我的结果?
-- Testing the test script --
^Cgiven how ticks work, this might not be called...

After sleep... this should not be executed if there was a signal interrupt.
In SIGINT cleanup
Shutting down

正如您可以从我的echo中看到的那样,我有点想知道 ticks的工作方式是否负责在处理信号之前完成start函数。我仍然认为这可能是事实。事实上,我不知道。
我在程序顶部声明了ticks:
declare(ticks = 1);

不立即处理信号对我造成了问题。例如,如果我在我的start函数中有这段代码(我已经测试过了),会发生什么?

$count = 0;
while(true){
    count++;
    echo "count\n";
    sleep(5);
}

即使我的cleanup函数有一个exit,由于SIGINT只是将我从sleep中唤醒,我永远不会到达那里,然后我继续循环并开始再次sleep。所以我的问题是:在PHP中,signal处理是如何工作的?我怎样才能保证当我收到一个信号时,它会立即被处理?我不仅想要一些可以解决这个问题的代码,我还想要一个解释(或至少是一个好的链接和摘要)。PHP版本:5.4.22,操作系统:Ubuntu 12.10。

我非常努力地尝试重现你的问题,而我唯一成功看到你的问题的方法是将“ticks”设置为大于1的值。你的PHP版本是多少?操作系统是什么?请发布你的PHP的“Configure Command”,以及一个展示出意外行为的完整工作代码示例。 - RandomSeed
1个回答

0

sleep() 会被某些信号打断,它将返回剩余的睡眠秒数,您可以像这样做来保持它睡眠。

.....
declare(ticks = 1);

$left = sleep(1000)
while ($left > 0) {
   $left = sleep($left);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接