在 PHP 中检测代码块的超时 [英] Detecting a timeout for a block of code in PHP

查看:54
本文介绍了在 PHP 中检测代码块的超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果在 PHP 中花费的时间太长,有没有办法中止代码块?也许是这样的:

Is there a way you can abort a block of code if it's taking too long in PHP? Perhaps something like:

//Set the max time to 2 seconds
$time = new TimeOut(2);
$time->startTime();

sleep(3)

$time->endTime();
if ($time->timeExpired()){
    echo 'This function took too long to execute and was aborted.';
} 

它不必完全像上面那样,但是是否有任何本机 PHP 函数或类可以执行此类操作?

It doesn't have to be exactly like above, but are there any native PHP functions or classes that do something like this?

编辑:Ben Lee 对 pcnt_fork 的回答将是完美的解决方案,只是它不适用于 Windows.有没有其他方法可以使用适用于 Windows 和 Linux 但不需要外部库的 PHP 来实现这一点?

Edit: Ben Lee's answer with pcnt_fork would be the perfect solution except that it's not available for Windows. Is there any other way to accomplish this with PHP that works for Windows and Linux, but doesn't require an external library?

编辑 2:XzKto 的解决方案在某些情况下有效,但不一致,无论我尝试什么,我似乎都无法捕捉到异常.用例是检测单元测试的超时.如果测试超时,我想终止它,然后继续下一个测试.

Edit 2: XzKto's solution works in some cases, but not consistently and I can't seem to catch the exception, no matter what I try. The use case is detecting a timeout for a unit test. If the test times out, I want to terminate it and then move on to the next test.

推荐答案

你可以通过 fork 进程来实现,然后使用父进程来监视子进程.pcntl_fork 是一种分叉进程的方法,因此您在内存中运行了两个几乎相同的程序平行线.唯一的区别是在一个进程中,父进程 pcntl_fork 返回一个正整数,它对应于子进程的进程 ID.而在另一个进程中,子进程 pcntl_fork 返回 0.

You can do this by forking the process, and then using the parent process to monitor the child process. pcntl_fork is a method that forks the process, so you have two nearly identical programs in memory running in parallel. The only difference is that in one process, the parent, pcntl_fork returns a positive integer which corresponds to the process id of the child process. And in the other process, the child, pcntl_fork returns 0.

这是一个例子:

$pid = pcntl_fork();
if ($pid == 0) {
    // this is the child process
} else {
    // this is the parent process, and we know the child process id is in $pid
}

这是基本结构.下一步是添加进程过期时间.您的东西将在子进程中运行,而父进程将仅负责监视和计时子进程.但是为了让一个进程(父进程)杀死另一个进程(子进程),需要有一个信号.信号是进程通信的方式,意思是你应该立即结束"的信号是 SIGKILL.您可以使用 posix_kill 发送此信号.所以父母应该等待 2 秒然后杀死孩子,就像这样:

That's the basic structure. Next step is to add a process expiration. Your stuff will run in the child process, and the parent process will be responsible only for monitoring and timing the child process. But in order for one process (the parent) to kill another (the child), there needs to be a signal. Signals are how processes communicate, and the signal that means "you should end immediately" is SIGKILL. You can send this signal using posix_kill. So the parent should just wait 2 seconds then kill the child, like so:

$pid = pcntl_fork();
if ($pid == 0) {
    // this is the child process
    // run your potentially time-consuming method
} else {
    // this is the parent process, and we know the child process id is in $pid
    sleep(2); // wait 2 seconds
    posix_kill($pid, SIGKILL); // then kill the child
}

这篇关于在 PHP 中检测代码块的超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆