Возможно ли сконвертировать фатальную ошибку исключение и потом поймать её?

Фанат

oncle terrible
Команда форума
PHP:
register_shutdown_function(function ()
{
    $error = error_get_last();
    if ($error !== null) {
        throw new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
    }
});
ini_set('memory_limit',1);
$a = range(1,100000);
Выдает как положено, Fatal error: Uncaught ErrorException:

Я радостно добавляю трай кетч
PHP:
register_shutdown_function(function ()
{
    $error = error_get_last();
    if ($error !== null) {
        throw new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
    }
});

try {
    ini_set('memory_limit',1);
    $a = range(1,100000);
} catch (Throwable $e) {
    echo "Caught: ".$e;
}
И... вышел таки снова на дерибасовскую

Я правильно понимаю что к моменту вызова register_shutdown_function у все рабочий день уже закончился и уже никакие механизмы работать не будут?
 

virus_net

Новичок
register_shutdown_function:
Регистрирует функцию callback, которая выполнится после завершения работы скрипта или при вызове функции exit().
Вам нужен set_error_handler:
Эта функция используется для определения собственного обработчика ошибок времени выполнения скрипта. Например, если требуется очистить данные/файлы, когда произошла критическая ошибка, или если нужно переключить тип ошибки, исходя из каких-то условий (используя функцию trigger_error()).
Пример:
Код:
set_error_handler("exception_error_handler");

function exception_error_handler($errno, $errstr, $errfile, $errline ){
    if ($errno != 2 && $errno != 8192){ //exept E_WARNING E_DEPRECATED
            ob_start();
            debug_print_backtrace( );
            $backtrace = ob_get_clean();
            logg(sprintf("+PHP ERROR %s: %s",$errno,$backtrace));
    }
return true;
}

function logg($text){
//do something with that
}
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
Есть catchable fatal errors, которые можно словить через set_error_handler.

А если не catchable, то ой, там уже zend vm в состоянии нестояния, можно сделать только что-то совсем простое типа логирования.
 

Фанат

oncle terrible
Команда форума
А если не catchable, то ой, там уже zend vm в состоянии нестояния, можно сделать только что-то совсем простое типа логирования.
Ага, спасибо, я так и думал!
Ну то есть остановимся примерно на таком?
PHP:
function MyExceptionHandler ($e)
{
    if (ini_get('display_errors')) {
        echo $e;
    } else {
        error_log($e);
        header('HTTP/1.1 500 Internal Server Error', TRUE, 500);
        echo "<h1>500 Internal Server Error</h1>
              An internal server error has been occurred.<br>
              Please try again later.";
    }
}

set_exception_handler('MyExceptionHandler');

set_error_handler(function ($level, $message, $file = '', $line = 0)
{
    throw new ErrorException($message, 0, $level, $file, $line);
});


register_shutdown_function(function ()
{
    $error = error_get_last();
    if ($error !== null) {
        MyExceptionHandler(new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']));
    }
});
 

Фанат

oncle terrible
Команда форума
:)))
Скоро будет 20 лет как, между прочим!

Оно, как пепел Клааса, стучит в моё сердце. Рвётся наружу.
У меня модус операнди такой.

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

флоппик

promotor fidei
Команда форума
Партнер клуба
Спасибо.
Я тут очередную эпохалку ваяю.
Хочу минимально работоспособный код сделать
Многие фреймворки/тулзы (симфони, сентри, еще в паре мест видел) еще резервируют немножко памяти (уебански создавая строку с мусором в памяти) чтоб ловить из фатальных - out of memory и успевать поработать
 

Фанат

oncle terrible
Команда форума
Многие фреймворки/тулзы (симфони, сентри, еще в паре мест видел) еще резервируют немножко памяти (уебански создавая строку с мусором в памяти) чтоб ловить из фатальных - out of memory и успевать поработать
Спаситбо.
Да, это я помню, меня здорово поразило, когда я впервые увидел в Ййи.
Я наверное об этом упомяну, но в код добавлять не буду. Моя задача как всегда сделать самый минимальный вариант, чтобы за деревьями был лес виден.
 

ksnk

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

Yoskaldyr

"Спамер"
Партнер клуба
А где именно в yii можно глянуть эту фишку с мусорной строкой?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Фишка с лишней памятью - пара строк в коде и параграф в описании. Если пара строк добавляет живучести - почему бы их не использовать ?
Позволяет избежать проблем, которых могло бы не быть, если бы не занятая память... ;)
 

fixxxer

К.О.
Партнер клуба
Плохо что каждый инструмент будет так делать, кмк (даже если используются все вместе)
Да так и происходит. Конечно, для современных серверов это ничего не значащие копейки, но как-то неаккуратненько.
Решением была бы библиотека, которую бы все использовали, но чтобы такое везде пропихнуть, нужен какой-нибудь PSR на эту тему.
 

Yoskaldyr

"Спамер"
Партнер клуба
А есть где либо объяснение почему это работает? С внутренностями работы GC PHP? почему этот резерв работает?
 

fixxxer

К.О.
Партнер клуба
Да вроде и так понятно: если при выделении памяти для очередного zval (или при realloc-е) ОС вернет ошибку out of memory, PHP дернет GC и попробует еще раз.
 

ksnk

прохожий
Не особо и копейки... В Yii2 это где-то тут yii2/base/ErrorHandler.php искать по слову _memoryReserve. YII грызет по дефолту 256к.
Проверил по одному yii2 проекту и такая же хрень еще в паре мест
монолог в подобном месте - 20к,
sentry - 10к.
Плохо, что все это в одном и том же проекте кучкуется...
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
А как здесь поможет PSR? Проблема вечная, решать ее надо через выделение резервной памяти, которая доступна только в shutdown function - это не PSR нужен, а RFC. Например, повышать лимит в shutdown function на указанное в php.ini количество байт.

Вторая подобная проблема - переполнение стека, как ее решать - я не понимаю. Куча тут не поможет.
 
Сверху