Fatal error php перехват

How can I catch a «catchable fatal error» on PHP type hinting?

For future reference: Exceptions in the engine (for PHP 7) — Beginning with PHP 7 it is possible catch fatal errors. This is also for the here discussed “Catchable fatal error” ( E_RECOVERABLE_ERROR ) as these be catched beginning with PHP 7..

1 Answer 1

Update: This is not a catchable fatal error anymore in php 7. Instead an «exception» is thrown. An «exception» (in scare quotes) that is not derived from Exception but Error; it’s still a Throwable and can be handled with a normal try-catch block. see https://wiki.php.net/rfc/throwable-interface

 > class ClassWrong<> class ClassB<> class ClassC extends ClassB <> foreach( array('ClassA', 'ClassWrong', 'ClassB', 'ClassC') as $cn ) < try< $a = new ClassA; $a->method_a(new $cn); > catch(Error $err) < echo "catched: ", $err->getMessage(), PHP_EOL; > > echo 'done.'; 
catched: Argument 1 passed to ClassA::method_a() must be an instance of ClassB, instance of ClassA given, called in [. ] catched: Argument 1 passed to ClassA::method_a() must be an instance of ClassB, instance of ClassWrong given, called in [. ] method_a: ClassB method_a: ClassC done. 

E_RECOVERABLE_ERROR ( integer )
Catchable fatal error. It indicates that a probably dangerous error occured, but did not leave the Engine in an unstable state. If the error is not caught by a user defined handle (see also set_error_handler()), the application aborts as it was an E_ERROR.

function myErrorHandler($errno, $errstr, $errfile, $errline) < if ( E_RECOVERABLE_ERROR===$errno ) < echo "'catched' catchable fatal error\n"; return true; >return false; > set_error_handler('myErrorHandler'); class ClassA < public function method_a (ClassB $b) <>> class ClassWrong<> $a = new ClassA; $a->method_a(new ClassWrong); echo 'done.'; 
'catched' catchable fatal error done. 

edit: But you can «make» it an exception you can handle with a try-catch block

function myErrorHandler($errno, $errstr, $errfile, $errline) < if ( E_RECOVERABLE_ERROR===$errno ) < echo "'catched' catchable fatal error\n"; throw new ErrorException($errstr, $errno, 0, $errfile, $errline); // return true; >return false; > set_error_handler('myErrorHandler'); class ClassA < public function method_a (ClassB $b) <>> class ClassWrong<> try< $a = new ClassA; $a->method_a(new ClassWrong); > catch(Exception $ex) < echo "catched\n"; >echo 'done.'; 

Источник

Читайте также:  Найти все числа армстронга python

Перехват fatal error или Перехват неперехватываемых ошибок

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

// мы будем сами обрабатывать ВСЕ ошибки error_reporting(E_ALL); // определенная пользователем функция обработки ошибок function userErrorHandler ($errno, $errmsg, $filename, $linenum, $vars) < // дата и время для записи об ошибке $dt = date("Y-m-d H:i:s (T)"); // определение ассоциативного массива строк ошибок // на самом деле следует рассматривать только элементы 2,8,256,512 и 1024 $errortype = array ( 1 =>"Ошибка", 2 => "Предупреждение", 4 => "Ошибка синтаксического анализа", 8 => "Замечание", 16 => "Ошибка ядра", 32 => "Предупреждение ядра", 64 => "Ошибка компиляции", 128 => "Предупреждение компиляции", 256 => "Ошибка пользователя", 512 => "Предупреждение пользователя", 1024=> "Замечание пользователя" ); // набор ошибок, для которого будут сохраняться значения переменных $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE); $err = $dt." ".$errortype[$errno]." № ".$errno."\n"; $err .= $errmsg."\n"; $err .= "Вызов из ".$filename." строка № ".$linenum."\n"; ob_end_clean(); ob_start(); print_r($vars); $v = "Переменные:".ob_get_contents()."\n"; ob_end_clean(); ob_start("error_callback"); // сохранить протокол ошибок и отправить его мылом mail('error@htmlweb.ru', 'PHP error report', $err.$v, "Content-Type: text/plain; charset=windows-1251" ) or die("Ошибка при отправке сообщения об ошибке"); error_log($err."\n", 3, dirname(__FILE__) . "/log/error.log") or die("Ошибка записи сообщения об ошибке в файл"); > function error_callback($buffer) < // если на экран будет выведено сообщение о фатальной ошибке, мы его сможем обработать if (preg_match("/error.*/",$buffer,$regs)) < $regs[0] = date("Y-m-d H:i:s (T)")."\n".preg_replace("/<[/]?b(r /)?>/","",$regs[0])."\n"; mail('error@htmlweb.ru', 'PHP error report', $regs[0], "Content-Type: text/plain; charset=windows-1251" ) or die("Ошибка при отправке сообщения об ошибке"); error_log($regs[0], 3, dirname(__FILE__) . "/log/error.log") or die("Ошибка записи сообщения об ошибке в файл"); return "Ошибка, выполнение прервано"; > else return $buffer; > // Перехват вывода на экран ob_start("error_callback"); // Перехват обработки ошибок $old_error_handler = set_error_handler("userErrorHandler");

Перехват fatal error в PHP

Следующий пример позволяет назначить функцию-обработчик завершения любого PHP скрипта. Этот обработчик получит управление и при возникновении fatal error.

// Определяем новую функцию-обработчик fatal error. function myShutdownHandler() < if (@is_array($e = @error_get_last())) < $code = isset($e['type']) ? $e['type'] : 0; $msg = isset($e['message']) ? $e['message'] : ''; $file = isset($e['file']) ? $e['file'] : ''; $line = isset($e['line']) ? $e['line'] : ''; if($code>0)userErrorHandler($code,$msg,$file,$line,''); > > register_shutdown_function('myShutdownHandler'); // вызываем ошибку: $x = null; $x->method();

userErrorHandler — процедура обработки ошибкок, описанная выше.

Источник

Перехват Fatal Error

В приведенном примере происходит попытка создания экземпляра неопределенного класса — Test1. После выполнения этого скрипта на почту придет письмо примерно со следующим содержимым: E_ERROR : Class ‘Tester1’ not found script.php 24

Текст и заголовок письма конечно же можно изменить или записывать данные в специальный файл. Плюс отправки сообщения на почту, в том, что на него можно оперативно среагировать.

Массив $e содержит следующие элементы:

  • type – тип ошибки, в примере это E_ERROR, остальные типы приведены в массиве $arError ;
  • message – текст ошибки;
  • file – файл в котором произошла ошибка;
  • line – строка на которой произошла ошибка;

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

Подключить bitrix без подключения шаблона сайта

В статье приводится пример кода подключения bitrix без подключения шаблона сайта. Так же описано когда это может пригодится.

CSS простой горизонтальный слайдер

В статье приводится пример кода для создания простого горизонтального слайдера с использованием CSS и небольшим количеством JS кода. Для реализации потребуется всего около 60 строк стилей и js кода.

PHP Удалить лишние нули после запятой

Когда в проекте диапазон чисел от 0,0001 до 1 000 000, удобно автоматически удалять лишнии нули после запятой.

Bitrix запись своих настроек в settings.php

Статья о том как разместить свои настройки не создавая велосипеды и костыли, а используя возможности системы.

Bitrix подключить класс компонента

В статье приводится пример того как можно подключить только компонент битрикс без подключения его шаблона, чтобы можно было вызвать его метод или получить значения свойств

Bitrix получить ID текущего покупателя

В статье приводится пример кода для получения ID текущего покупателя в bitrix.

Источник

Как обрабатывать Fatal Error в PHP

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

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

Для треккинга процессов (демонов), очень удобно пользоваться наблюдателями за процессами, такими как monit, мы используем monit для мониторинга сисстемных демонов. Кстати, на хабре недавно была статья о моните.
Но речь не о нем 🙂

Я попросил одного из разработчиков моей команды сделать нормальный обработчик фатальной ошибки в коде менеджера очереди, а именно форк нового инстанса обработчика и логирование ошибки по типу события. На это я получил ответ, что в php фатальные ошибки обрабатывать в принципе невозможно и позорно об этом не знать и что: «компьютерные науки на текущем этапе своего эволюционного развития еще не располагают алгоритмами способными решить поставленную задачу опираясь на возможности php коректно. »

После этого я написал такой код, который обрабатывает фатальные, а также все другие ошибки в php приложении. Если кому-то еще он поможет, то я буду только рад.

ini_set( «display_errors» , «on» );
error_reporting(E_ALL);
ini_set( ‘html_errors’ , ‘on’ );

function fatal_error_handler($buffer) if (preg_match( «|(Fatal error:)(.+)( file_put_contents( «php://stderr» , «before fork (pid: » . getmypid() . «)\n» );
system( «php tester.php » . getmypid() . » &» );
return «ERROR CAUGHT, check log file» ;
>
return $buffer;
>

//code between ob_start and ob_end_flush is included by MQ Handler, so we know nothing about it, and this code could fire a Fatal Error
if (isset($_SERVER[ «argv» ][1])) file_put_contents( «php://stderr» , «kill : » .var_export(posix_kill($_SERVER[ ‘argv’ ][1], 15), true ). «\n» );
>
ob_start( «fatal_error_handler» );
set_error_handler( «handle_error» );

while ( true ) //Just a Warning
//$a = 9/0;
sleep(10);
file_put_contents( «php://stderr» , «live\n» );
//Fatal error — вызов необъявленной ф-ии
if (rand(1,10) % 2 == 1) ololo(123);
>
>

echo «Program still executing. » ;

* This source code was highlighted with Source Code Highlighter .

Небольшое объяснение по текущему коду.
Fatal Error — мы ловим через буферизацию вывода в ф-ии fatal_error_handler
Остальные ошибки (все кроме фатальных) обрабатываются ф-ией handle_error
Если ошибок нет — код выполняется нормально 🙂

Да, это также не является единственным средством high availability и отказоустойчивости.
Мы пытаемся запустить демон каждую минуту по крону, а код демона начинается ф-ией

if (!checkSingleProcess()) exit;
>

function checkSingleProcess() $res = exec( ‘ps aux | grep mq_manager.php | grep -v grep | grep -v ‘ .getmypid(), $output, $ return );
return $output == array();
>

* This source code was highlighted with Source Code Highlighter .

т.е. если демон запущен, то мы прекращаем выполнение.

Открыт ко всем мнения и по возможности буду отвечать на все комментарии.

UPD: обратите внимание на ini_set(‘html_errors’, ‘on’); я потратил с пол часа времени не понимая почему обработчик не работает из-под CLI. Дело было как раз в HTML-ных ошибках. Т.к. из-под CLI они давались без HTML тегов, и условие preg_match(«|(Fatal error:)(.+)(

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

Источник

Оцените статью