Безопасное обнаружение ошибки «Разрешенная память»

У меня есть сценарий шлюза, который возвращает JSON обратно клиенту. В сценарии я использую set_error_handler, чтобы ловить ошибки и все еще иметь отформатированный возврат.

Он подвержен ошибкам «Разрешенные размеры памяти», а не увеличивает ограничение памяти с помощью чего-то вроде ini_set ('memory_limit', '19T') , я просто хочу вернуть, что пользователь должен попробовать что-то еще, потому что он использовал много Память.

Есть ли хорошие способы уловить фатальные ошибки?

Как следует из этого ответа , вы можете использовать register_shutdown_function() для регистрации обратного вызова, который будет проверять error_get_last() .

Вам все равно придется управлять выходом, генерируемым из-за нарушения кода, либо с помощью оператора @ ( shut up ), либо ini_set('display_errors', false)

 ini_set('display_errors', false); error_reporting(-1); set_error_handler(function($code, $string, $file, $line){ throw new ErrorException($string, null, $code, $file, $line); }); register_shutdown_function(function(){ $error = error_get_last(); if(null !== $error) { echo 'Caught at shutdown'; } }); try { while(true) { $data .= str_repeat('#', PHP_INT_MAX); } } catch(\Exception $exception) { echo 'Caught in try/catch'; } в ini_set('display_errors', false); error_reporting(-1); set_error_handler(function($code, $string, $file, $line){ throw new ErrorException($string, null, $code, $file, $line); }); register_shutdown_function(function(){ $error = error_get_last(); if(null !== $error) { echo 'Caught at shutdown'; } }); try { while(true) { $data .= str_repeat('#', PHP_INT_MAX); } } catch(\Exception $exception) { echo 'Caught in try/catch'; } 

При запуске эти выходы Caught at shutdown . К сожалению, ErrorException исключения ErrorException не вызывается, потому что фатальная ошибка запускает завершение скрипта, впоследствии попадая только в функцию выключения.

Вы можете проверить массив $error в функции выключения для получения подробной информации о причине и ответить соответствующим образом. Одно предложение может повторить запрос обратно на ваше веб-приложение ( на другом адресе или с разными параметрами ) и вернуть захваченный ответ.

Я рекомендую сохранять error_reporting() high ( значение -1 ), хотя и использовать ( как другие предложили ) обработку ошибок для всего остального с помощью set_error_handler() и ErrorException .

Если вам необходимо выполнить бизнес-код при возникновении этой ошибки (ведение журнала, резервное копирование контекста для будущих отладок, отправка по электронной почте или тому подобное), регистрации функции выключения недостаточно: вы должны освободить память в некотором роде.

Одним из решений является выделение некоторой аварийной памяти:

 public function initErrorHandler() { // This storage is freed on error (case of allowed memory exhausted) $this->memory = str_repeat('*', 1024 * 1024); register_shutdown_function(function() { $this->memory = null; if ((!is_null($err = error_get_last())) && (!in_array($err['type'], array (E_NOTICE, E_WARNING)))) { // $this->emergencyMethod($err); } }); return $this; } 

вы можете получить размер памяти, уже потребляемой процессом, используя эту функцию. memory_get_peak_usage документация находится по адресу http://www.php.net/manual/en/function.memory-get-peak-usage.php. Я думаю, что это быть проще, если бы вы могли добавить условие для перенаправления или остановки процесса до того, как этот процесс почти достигнет предела памяти. 🙂