PHP 睡眠、pcntl_signal 和滴答声

Posted

技术标签:

【中文标题】PHP 睡眠、pcntl_signal 和滴答声【英文标题】:PHP sleep, pcntl_signal, and ticks 【发布时间】:2014-05-24 23:00:20 【问题描述】:

好的,所以我一直在尝试让 Process Signalsphp 脚本一起工作。我遇到了很多我不确定发生了什么的事情,而且我觉得文档并不能很好地解释它。

假设我按照registering signals 上的示例进行操作:

<?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);

然后在我对这个过程的测试中,我做了一些简单的sleeps 和echos(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

正如您从我的echos 中看到的那样,我有点想也许ticks 工作负责完成start 函数在处理信号之前。我仍然认为可能是这种情况。事实是,我只是不知道。

我确实在我的程序顶部声明了ticks

declare(ticks = 1);

不立即处理信号会给我带来问题。例如,如果我的 start 函数中有这段代码(并且我已经对此进行了测试)怎么办?

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

即使我的cleanup 函数有一个exit,我也永远无法达到那个目标,因为SIGINT 只会让我脱离sleep,然后我继续循环并再次开始sleeping。

所以这是我的问题:signal 处理在PHP 中如何工作?如何保证当我收到信号时,立即处理?我不只是想要一些可以解决这个问题的代码,我想要一个解释(或者至少是一个好的链接和摘要)。

PHP 版本:5.4.22

操作系统:Ubuntu 12.10

【问题讨论】:

我非常努力地重现了您的问题,而我设法看到您的问题的唯一方法是将ticks 设置为大于 1 的值。您的 PHP 版本是多少?操作系统?请发布您的 PHP 的“配置命令”,以及表现出意外行为的完整工作代码示例。 【参考方案1】:

sleep() 会被某个信号击倒,它会返回左睡眠秒数,你可以这样做让它保持睡眠状态。

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

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

【讨论】:

以上是关于PHP 睡眠、pcntl_signal 和滴答声的主要内容,如果未能解决你的问题,请参考以下文章

如何使时钟秒针以每秒 4 次跳动/滴答声移动?

为啥每拍的滴答声很大,而时间却很小?

wav文件中奇怪的滴答声

在另一个线程中独立计时 For 循环的每个滴答声的最佳方法

Android mic 的灵敏度足以听手表滴答声? [关闭]

AVAudioPlayer 在停止或恢复时“滴答”