使用自定义SIGTERM处理程序时的Segfaulting

时间:2016-01-11 23:11:11

标签: php symfony signals

我有一个无限期运行的PHP脚本,我正在努力使它能够在收到SIGTERM信号时正常关闭。此脚本是大型Symfony2代码库的一部分,因此“脚本”实际上是一个由命令启动的服务。基本上,我在服务类$shouldBeAlive中有一个布尔值。我有一个while(true)循环,用于检查每次迭代开始时$shouldBeAlive是否仍然为真。然后我有一个信号处理程序,它在while(true)循环启动之前设置,如果抛出SIGTERM,则将$shouldBeAlive设置为false,这样循环将完成当前迭代,然后立即退出在下一次迭代开始时。

在我对信号和诸如此类的理解中,所有这一切都应该可行。但相反,每次我将SIGTERM发送到php进程(我使用Segmentation fault: 11)时,我都会收到一条消息kill <pid>。我已经尝试使用Xdebug跟踪来找到问题的根源,但我无法从中找出一个明显的问题(同样,Xdebug生成的跟踪文件是8-10MB)。

以下是我的服务类的简化版本:

class WorkerService extends AbstractService
{
    private $shouldBeAlive;

    // called by the constructor of this class
    protected function setup()
    {
        $this->shouldBeAlive = false;
    }

    // called when my command wants to make the work begin
    public function go()
    {
        $this->shouldBeAlive = true;

        // set signal handler to `$this->handleSignal($signo)`
        assert(pcntl_signal(SIGTERM, [$this, "handleSignal"]));

        $this->work();
    }


    public function handleSignal($signo)
    {
        // make the worker terminate on next loop completion
        $this->shouldBeAlive = false;

        // restore the default handler for this signal
        assert(pcntl_signal($signo, SIG_DFL));

        echo "Signal received, shutting down gracefully... (send signal again to force immediate shutdown)";
        return;
    }

    public function work()
    {
        while (true) {
            // make PHP fire any waiting signals
            pcntl_signal_dispatch();

            // break out of the loop if we're supposed to be dead
            if (!$this->shouldBeAlive) break;

            // ...
            // I'm omitting the actual loop logic. Basically, it makes some
            // HTTP requests, sometimes starts another process with proc_open(),
            // and eventually it'll sleep for a couple seconds and continue.
        }
    }
}

似乎我的handleSignal($ signo)方法根本就没有被调用过,因为没有多少调整可以解决这个问题。我也尝试在go()方法中使用declare(ticks = 1);而不是在while(true)循环中调用pcntl_signal_dispatch();,它仍然是段错误(以及我理解事物的方式,这样做反正没有意义)。有谁看到我可能会遗漏或误解?

0 个答案:

没有答案