1

我有一个用 PHP 编写的软件,可以运行很长时间,它是通过命令行(不是 Web 应用程序)启动的。我想确保在软件退出时调用一个函数,包括通过 ctrl+c 杀死时。当被信号杀死时,不会调用关闭函数(通过 register_shutdown_fucntion() 注册的析构函数和函数)。

经过一番阅读,我意识到我必须在每个相关信号上添加一个处理程序才能调用“exit;”。这样做解决了我的问题并且有效。

我的问题是,在某些情况下,信号没有立即处理。它可能需要几秒钟,几分钟,在某些情况下,根本不处理。就像从未到达处理程序代码一样。我真的不知道从哪里开始调试。我尝试过其他信号(sigkill、sighup 等),行为相同。

我的代码带有这些括号

declare(ticks=1)
{...}

我找不到立即治疗的时间和不接受治疗的时间之间的任何相关性。

任何帮助,将不胜感激。

4

2 回答 2

2

信号应该这样处理:首先,你必须像这样制作一个信号处理程序:

function signalHandler($signo = null) {
    $pid = posix_getpid();
    switch ($signo) {
        //case SIGKILL: // you can't override SIGKILL so it is useless
        case SIGTERM:
        case SIGINT:
            // unexpected shut down
            exit(3);
            break;
        case SIGCHLD:
        case SIGHUP:
            // just ignore it
            break;
        case 10:
            // user signal 1 received. Process exited normally
            exit(0);
            break;
        case 12:
            // user signal 2 received. Precess exited with a catched error
            exit(3);
            break;
        default:
            // ignore other signals
    }
}

然后,在你的主进程中,你必须告诉 PCNTL 你正在使用这个处理程序:

    pcntl_signal(SIGTERM, "signalHandler");
    pcntl_signal(SIGINT, "signalHandler");
//  pcntl_signal(SIGKILL, "signalHandler"); // you can't override SIGKILL so it is useless
    pcntl_signal(SIGCHLD, "signalHandler");
    pcntl_signal(SIGHUP, "signalHandler");
    pcntl_signal(10, "signalHandler");
    pcntl_signal(12, "signalHandler");

我正在使用它,似乎可以为 200 个进程工作,同时运行 8 个进程,每个进程 10 秒。

在这里,当一个进程退出时,他发送一个信号 10 或 12(表示成功或错误)使用posix_kill($pid, 10)

于 2015-05-26T15:15:54.320 回答
0

我认为这里的问题是,也许您调用了一个包含循环的函数,并且循环的每次迭代都需要大量时间(例如,从数据库中获取数据)。在这种情况下,当您的程序接收到停止信号时,它会将此信号添加到堆栈中,等待,直到从数据库中获取数据,然后调用信号处理函数。

我也在寻找一种立即调用信号处理函数的方法。也许PHP只是没有这个选项。

更新:

我想我找到了解决方案。尝试false作为第三个参数传递给函数pcntl_signal(),如下所示:

pcntl_signal(SIGINT, function () {
    echo 'Do something here.';
}, false);
于 2021-05-17T12:43:10.720 回答