如何捕获致命错误:PHP中超过30秒的最大执行时间

ing*_*.am 54 php try-catch fatal-error

我一直在玩一个我正在开发的系统,并设法让它导致这个:

致命错误:超出最长执行时间30秒

它发生在我做一些不切实际的事情时,但它可能发生在用户身上.

有谁知道是否有办法捕捉这个例外?我已经读过了,但似乎每个人都建议增加允许的时间.

小智 75

如何尝试PHP文档(嗯......至少有一个读者)说:

<?php
function shutdown()
{
 $a = error_get_last();

 if ($a == null) {echo "No errors";}
 else {print_r($a);}
}

register_shutdown_function('shutdown');
ini_set('max_execution_time', 1);
sleep(3);
?>
Run Code Online (Sandbox Code Playgroud)

看看以下链接:

  1. http://www.php.net/manual/en/function.set-error-handler.php#106061
  2. http://www.php.net/manual/en/function.register-shutdown-function.php

  • 这可能是我从未见过的最好的秘密.真棒. (8认同)
  • sleep()实际上并不影响时间限制计数器,这很奇怪,但却是真的.所以你应该做一些其他事情来测试你的shutdown()函数 - 一些嵌套的for循环,每次迭代一百万次应该这样做. (6认同)
  • @BobbyJack虽然很奇怪,但是因为睡眠线程停止执行一段时间后才有意义.因为它没有执行,所以该时间不被视为已执行的执行时间. (3认同)
  • 我测试过。但仍然显示致命错误消息。能不能避免呢。我以任何方式使用 ini_set('display_errors', '0'); (2认同)

cwa*_*ole 27

您唯一的选择是增加脚本的允许执行时间(将其设置为0使其无限,但不建议)或生成新线程并希望获得最佳效果.

这是不可捕获的原因是它并没有真正抛出.没有一行代码实际上触发了错误,而PHP说,"不,抱歉,这太长了.现在是时候关闭了." 这是有道理的.想象一下,一个脚本的最大执行时间为30秒,捕获该错误并再花30秒...在一个设计不佳的程序中,这开辟了一些相当讨厌的机会来利用.它至少会为DOS攻击创造机会.

  • 我反对通过PHP对编码缺陷是否允许无限循环或DOS漏洞等进行保密.我认为应该由程序员来处理错误.也许在cURL期间发生超时,我希望页面无限刷新,直到它重新连接到url(因为T1线路关闭,或者远程服务器,谁知道?).我不希望我的预处理器,无论是php,asp,cgi等,都能为我做出决定.我不认为预处理器,甚至像javascript这样的客户端语言应该代表我做出道德或道德决定. (3认同)

Gor*_*onM 18

这不是一个例外,这是一个错误.异常和错误之间存在重要差异,首先和最重要的错误无法通过try/catch语义捕获.

PHP脚本是围绕短执行时间的范例构建的,因此PHP默认配置为假设如果脚本运行时间超过30秒,则必须在无限循环中捕获它,因此应该终止.这是为了防止错误的PHP脚本导致拒绝服务,无论是意外还是恶意.

但是,脚本有时需要比默认分配的脚本更多的运行时间.

你可以尝试改变最大执行时间,无论是使用set_time_limit()或改变的值max_execution_timephp.ini的文件,提高了极限.您也可以通过将执行时间设置为0来完全删除限制,但不建议这样做.

set_time_limit()可能会因为disable_functions您可能无法使用的机制而被禁用,您也可能无法访问php.ini.如果两者都是这种情况,那么您应该联系您的主人寻求帮助.

一个例外是从运行PHP脚本的命令行.在这些运行条件下,PHP脚本可能是交互式的,需要花费很长时间处理数据或等待输入.因此max_execution_time,默认情况下,从命令行运行的脚本没有限制.


编辑添加:PHP 7的错误处理进行了重大改革.我相信错误和异常现在都是Throwable的子类.这可能使上述内容不再与PHP7 +相关,但我必须更仔细地研究错误处理现在如何运作的具体细节.


pin*_*sia 8

你无能为力.但您可以使用register_shutdown_function进行正常关机

<?php 

ini_set('display_errors', '0');         
ini_set("max_execution_time",15 ); //you can use this if you know your script should not take longer than 15 seconds to finish

register_shutdown_function('shutdown');


function shutdown() 
{ 
       $error = error_get_last();

       if ($error['type'] === E_ERROR) {

      //do your shutdown stuff here
      //be care full do not call any other function from within shutdown function
      //as php may not wait until that function finishes
      //its a strange behavior. During testing I realized that if function is called 
      //from here that function may or may not finish and code below that function
      //call may or may not get executed. every time I had a different result. 

      // e.g.

      other_function();

      //code below this function may not get executed

       } 

} 

while(true)
{

}

function other_function()
{
  //code in this function may not get executed if this function
  //called from shutdown function
} 

?>
Run Code Online (Sandbox Code Playgroud)


小智 5

是的,我通过TheJanOnline测试了解决方案.sleep()不计入php执行时间所以这里是无限循环的WORKING版本:

<?php 
function shutdown() 
 { 
     $a=error_get_last(); 
     if($a==null)   
         echo "No errors"; 
     else 
          print_r($a); 

 } 
register_shutdown_function('shutdown'); 
ini_set('max_execution_time',1 ); 
while(1) {/*nothing*/}
// will die after 1 sec and print error
?>
Run Code Online (Sandbox Code Playgroud)