Я построил простой класс 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
все равно будет отключено.Тем не менее, я не совсем доволен этим решением, так как оно не очень «чистое».