Как отловить фатальную ошибку: в PHP превышено максимальное время выполнения 30 секунд - PullRequest
54 голосов
/ 28 июля 2011

Я играл с системой, которую разрабатываю, и мне удалось заставить ее вызвать это:

Неустранимая ошибка: превышено максимальное время выполнения 30 секунд

Это произошло, когда я делал что-то нереальное, но, тем не менее, это могло случиться с пользователем.

Кто-нибудь знает, есть ли способ поймать это исключение? Я читал вокруг, но все, кажется, предлагают увеличить время.

Ответы [ 8 ]

72 голосов
/ 29 июля 2012

Как насчет того, чтобы в документации 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); 
?>

Посмотрите следующие ссылки:

  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
26 голосов
/ 28 июля 2011

Ваши единственные варианты - увеличить допустимое время выполнения (установка его в 0 делает его бесконечным, но это не рекомендуется) скрипта или создать новый поток и надеяться на лучшее.

Причинато, что это не уловимо, - то, что это действительно не брошено.Ни одна строка кода на самом деле не вызвала ошибку, скорее PHP сказал: «Нет, извините, это слишком долго. Время закрывать сейчас».И это имеет смысл.Представьте себе, что сценарий с максимальным временем выполнения 30 секунд перехватывает эту ошибку и занимает еще 30 секунд ... в плохо спроектированной программе, что открывает некоторые довольно неприятные возможности для использования.Как минимум, это создаст возможности для DOS атак.

18 голосов
/ 28 июля 2011

Это не исключение, это ошибка. Существуют важные различия между исключениями и ошибками, в первую очередь ошибки не могут быть обнаружены с помощью семантики try / catch.

PHP-сценарии построены на основе парадигмы короткого времени выполнения, поэтому PHP по умолчанию настроен так, чтобы предполагать, что если сценарий выполняется более 30 секунд, его необходимо перехватить в бесконечном цикле и, следовательно, следует прервать. Это сделано для того, чтобы ошибочный сценарий PHP вызывал отказ в обслуживании либо случайно, либо по злому умыслу.

Однако сценариям иногда требуется больше времени выполнения, чем они выделены по умолчанию.

Вы можете попробовать изменить максимальное время выполнения, используя set_time_limit() или изменив значение max_execution_time в файле php.ini для увеличения лимита. Вы также можете полностью снять ограничение, установив время выполнения на 0, хотя это не рекомендуется.

set_time_limit() могут быть отключены такими механизмами, как disable_functions, поэтому он может быть недоступен для вас, также вы не можете иметь доступ к php.ini. Если это так, то вам следует обратиться за помощью к вашему хосту.

Исключением являются PHP-скрипты, запускаемые из командной строки . В этих условиях работы PHP-скрипты могут быть интерактивными и требовать много времени для обработки данных или ожидания ввода. По этой причине не существует ограничения max_execution_time для сценариев, запускаемых из командной строки по умолчанию.


EDIT TO ADD : в обработке ошибок PHP 7 произошел серьезный пересмотр. Я считаю, что ошибки и исключения теперь являются подклассами Throwable. Это может сделать вышеупомянутое больше не релевантным для PHP7 +, хотя мне придется более подробно изучить особенности того, как обработка ошибок работает сейчас, чтобы быть уверенным.

8 голосов
/ 16 марта 2013

С этим ничего не поделаешь. но вы можете корректно завершить работу с помощью 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
} 

?>
5 голосов
/ 05 января 2017

Да, я тестировал решение от TheJanOnline.sleep () не учитывает время выполнения 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 ); 
while(1) {/*nothing*/}
// will die after 1 sec and print error
?>
4 голосов
/ 16 июня 2016

Я придумал это, основываясь на ответе, который дал @ pinkal-vansia. Так что я не претендую на оригинальный ответ, а на ответ с практическим применением. Мне нужен был способ обновления страницы в случае тайм-аута. Поскольку я наблюдал достаточно времени ожидания моего сценария cURL, чтобы знать, что код работает, но иногда по какой-то причине он не может подключиться к удаленному серверу или полностью прочитать обслуживаемый html, и что при обновлении проблема исчезает, я я в порядке с обновлением сценария, чтобы "вылечить" ошибку максимального времени ожидания выполнения.

<?php //script name: scrape_script.php

ini_set('max_execution_time', 300);

register_shutdown_function('shutdown');

function shutdown() 
{ 
    ?><meta http-equiv="refresh" content="0; url=scrape_script.php"><?php
    // just do a meta refresh. Haven't tested with header location, but
    // this works fine.
}

К вашему сведению, 300 секунд - это не слишком много для скрипта очистки, который я запускаю, а для извлечения данных из типов страниц, которые я копирую, требуется чуть меньше. Иногда это происходит всего на несколько секунд только из-за нарушений соединения. Зная, что иногда происходит сбой соединения, а не обработка сценария, лучше не увеличивать время ожидания, а просто автоматически обновить страницу и повторить попытку.

4 голосов
/ 02 августа 2014

Существует несколько хитрый способ обработки "Неустранимая ошибка: превышено максимальное время выполнения 30 секунд" как исключение в некоторых случаях:

function time_sublimit($k = 0.8) {
    $limit = ini_get('max_execution_time'); // changes even when you set_time_limit()
    $sub_limit = round($limit * $k);
    if($sub_limit === 0) {
        $sub_limit = INF;
    }
    return $sub_limit;
}

В вашем коде вы должны измерить время выполнения и выдать исключениераньше, чем тайм-аут фатальная ошибка может быть вызвана.$ k = 0,8 - это 80% допустимого времени выполнения, поэтому у вас есть 20% времени для обработки исключения.

try{
    $t1 = time(); // start to mesure time.
    while (true) { // put your long-time loop condition here
        time_spent = time() - $t1;
        if(time_spent >= time_sublimit()) {
            throw new Exception('Time sublimit reached');
        }
        // do work here
    }
} catch(Exception $e) {
    // catch exception here
}
0 голосов
/ 28 июля 2011

поместите это в начало php файла

<?php
    set_time_limit(0);

РЕДАКТИРОВАТЬ 1

но сначала проверьте, нет ли такого кода:

while (1=1) {
  echo '=)';
}

РЕДАКТИРОВАТЬ 2

чтобы уловить эту ошибку, посмотрите set_error_handler

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...