ExceptionHandler не перехватывает все неперехваченные исключения - PullRequest
3 голосов
/ 09 января 2012

Я построил простой класс ExceptionHandler:

class ExceptionHandler{

    public function __construct(){

        set_exception_handler(array($this, 'handleException'));
    }

    public function handleException(\Exception $exception){
        echo $exception->getMessage() . $exception->getLine() .  $exception->getFile());

    }
}

Объект ExceptionHandler создается в самый короткий момент во время обработки.Компонент сеанса, который использует базу данных для хранения своих данных, создается вскоре после ExceptionHandler.

Компонент сеанса устанавливает следующее для правильного закрытия сеансов при использовании APC:

register_shutdown_function('session_write_close'); 

Iзатем выполнил тест, выключив мой сервер MySQL и запустив приложениеЧто озадачивает то, что исключение перехватывается ExceptionHandler, но в то же время остается необработанным и выводится xdebug:

SQLSTATE[HY000] [2002] ????,??????????? at line 133 in RedBean_Driver_PDO.php. //This is generated by my exception handler

//These were uncaught and processed by Xdebug
Fatal error: Uncaught exception 'Exception' with message 'PDO::__construct() [133

( ! ) Exception: PDO::__construct() [pdo.--construct]: [2002] ????,??????????? (trying to connect via tcp://localhost:3306) in RedBean_Driver_PDO.php on line 133

Call Stack
//Call stack

Что может быть причиной этого?Насколько я понимаю, ExceptionHandler должен быть в состоянии перехватить ВСЕ неперехваченные исключения, кроме любых исключений, которые выбрасываются в обновлении ExceptionHandler.

: у меня есть ощущение, что это имеет дело с session_write_close, которыйвызывается при отключении.Для session_write_close требуется доступ к базе данных, но база данных недоступна.Затем выдается исключение.Поскольку выполнение скрипта закончилось, ExceptionHandler недоступен, поэтому мы получаем необработанное исключение.Есть ли что-нибудь подобное?

Я запускаю php 5.3.9 в качестве fcgi на apache 2.2, используя mod_cgi на машине с Windows 7.

Трассировка стека:

#   Time    Memory  Function
1   2.0323  767336  ExceptionHandler->handleException( ) //Initial exception caught + handled
2   2.0334  773968  Session->write( ) //Script shutdown started (session_write_close to database)
3   2.0335  774344  Database->findOne( )
4   2.0335  774640  Database->__call( )
5   2.0335  774728  call_user_func_array( )
6   2.0335  775016  RedBean_Facade::findOne( )
7   2.0335  775016  RedBean_Facade::find( )
8   2.0335  775384  RedBean_OODB->find( )
9   2.0335  775384  RedBean_QueryWriter_AQueryWriter->selectRecord( )
10  2.0335  775448  RedBean_QueryWriter_AQueryWriter->safeTable( )
11  2.0335  775536  RedBean_QueryWriter_AQueryWriter->check( )
12  2.0335  775536  RedBean_Adapter_DBAdapter->escape( )
13  2.0335  775536  RedBean_Driver_PDO->Escape( )
14  2.0335  775536  RedBean_Driver_PDO->connect( )
15  2.0336  776200  PDO->__construct( ) //Cannot connect to database
16  4.0433  782768  ErrorHandler->handleError( ) //Error converted to exception

У меня такое чувство, что этого нельзя избежать, и в производственной среде display_errors все равно будет отключено.Тем не менее, я не совсем доволен этим решением, так как оно не очень «чистое».

1 Ответ

1 голос
/ 14 июня 2013

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

// This must be called before any code is executed
register_shutdown_function( 'shutdownFunction' );

function shutdownFunction() {
    // process code - be careful not to throw another fatal exception
    try {
        call_user_func( 'session_write_close' );
    } catch() {}
    ob_clean();
}

... кроме этого, я думаю, что вы застряли

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