(PHP) 等待子进程超时退出
(PHP) wait for child process to exit with timeout
我用 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 毫秒内完成,那么等待 sleep() 的 99 毫秒(相对)浪费了很多时间,otoh 我可以每 1 毫秒检查一次而不是每 100 毫秒,但那会浪费很多cpu。使用 linux api 可能会使用 sigtimedwait() to wait for SIGCHLD,但在 PHP 中我怀疑(但尚未正确验证)PHP 解释器本身会拦截并隐藏来自 userland php 代码的 SIGCHLD,所以..有什么建议吗?
我只是好奇,有必要使用proc_open()吗?因为作为您的示例代码,可以使用 exec() 函数来完成它,但它需要一个简单的 CLI 工具来使用,它的 timeout
.
timeout - run a command with a time limit Start COMMAND, and kill it
if still running after DURATION
因此此代码可替代您的代码,除非您想对 child 执行其他操作。
$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 中使用这个技巧进行多处理。它非常适合我。
我用 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 毫秒内完成,那么等待 sleep() 的 99 毫秒(相对)浪费了很多时间,otoh 我可以每 1 毫秒检查一次而不是每 100 毫秒,但那会浪费很多cpu。使用 linux api 可能会使用 sigtimedwait() to wait for SIGCHLD,但在 PHP 中我怀疑(但尚未正确验证)PHP 解释器本身会拦截并隐藏来自 userland php 代码的 SIGCHLD,所以..有什么建议吗?
我只是好奇,有必要使用proc_open()吗?因为作为您的示例代码,可以使用 exec() 函数来完成它,但它需要一个简单的 CLI 工具来使用,它的 timeout
.
timeout - run a command with a time limit Start COMMAND, and kill it if still running after DURATION
因此此代码可替代您的代码,除非您想对 child 执行其他操作。
$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 中使用这个技巧进行多处理。它非常适合我。