代码之家  ›  专栏  ›  技术社区  ›  hanshenrik

(PHP)等待子进程退出并超时

  •  0
  • hanshenrik  · 技术社区  · 5 年前

    我用proc_open()启动了一个子进程,现在我需要等到子进程完成——或者——直到X秒过去,以先到者为准。解决这个问题的一个显而易见的方法是使用while()循环,它会在每次迭代中进行如下检查:

    $starttime = microtime(true);
    $unused = [];
    $ph = proc_open($cmd, $unused, $unused);
    $terminated = false; // < protection against running pkilltree() twice
    // OPTIMIZE ME: use stream_select() or something instead of sleep-loop
    while (($status = proc_get_status($ph))['running']) {
        usleep(100 * 1000); // *1000 = ms
        if (! $terminated && microtime(true) - $starttime > MAX_RUNTIME_SECONDS) {
            $terminated = true;
            echo 'max runtime reached (' . MAX_RUNTIME_SECONDS . ' seconds), terminating...';
            pkilltree((int) ($status['pid']));
            // proc_terminate ( $ph, SIGKILL );
        }
    }
    

    然而,如果进程在1毫秒内完成,那么等待99毫秒的sleep()会(相对地)浪费很多时间,我可以每1毫秒检查一次,而不是每100秒检查一次,但这会浪费很多cpu。有了linux api,人们可能会使用 sigtimedwait() to wait for SIGCHLD ,但在PHP中,我怀疑(但尚未正确验证)PHP解释器本身拦截并隐藏了来自userland PHP代码的SIGCHLD,所以。。有什么建议吗?

    0 回复  |  直到 5 年前
        1
  •  2
  •   Mohammed Alhanafi    5 年前

    我只是好奇,有必要使用proc_open()吗?因为作为示例代码,可以使用exec()函数来实现,但它需要一个简单的CLI工具来使用 timeout .

    超时-使用限时启动命令运行命令,并将其杀死 如果持续时间过后仍在运行

    所以这个代码是你的代码的替代品,除非你想对孩子做其他事情。

    $starttime = microtime(true);
    exec("timeout " . MAX_RUNTIME_SECONDS . " $cmd");
    $terminated = false;
    if (! $terminated && microtime(true) - $starttime > MAX_RUNTIME_SECONDS) {
        $terminated = true;
        echo 'max runtime reached (' . MAX_RUNTIME_SECONDS . ' seconds), terminating...';
    }
    

    这是我多年来在PHP中使用的多处理技巧。这对我来说非常有效。