I have built a simple ExceptionHandler class:
class ExceptionHandler{
public function __construct(){
set_exception_handler(array($this, 'handleException'));
}
public function handleException(\Exception $exception){
echo $exception->getMessage() . $exception->getLine() . $exception->getFile());
}
}
The ExceptionHandler object is created at the earliest possible moment during processing. A Session component which uses the database for storing it's data is constructed shortly after the ExceptionHandler.
The session component sets the following to properly close a sessions when APC is used:
register_shutdown_function('session_write_close');
I then performed a test by shutting down my MySQL server and running the application. What is puzzling is that the exception is caught by ExceptionHandler, but at the same time remains uncaught and is outputted by 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
What could be causing this? My understanding is that the ExceptionHandler should be able to catch ALL uncaught exceptions except any exceptions that is thrown within the ExceptionHandler.
Update:
I have a feeling that this has to deal with session_write_close which is called on shutdown. session_write_close needs access to the database, but the database is unavaliable. An exception is then thrown. Since script execution has ended, ExceptionHandler is unavaliable, so we get an uncaught exception. Are there anyways around this?
I am running php 5.3.9 as fcgi on apache 2.2 using mod_cgi on a windows 7 machine.
A stack trace:
# 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
I have a feeling that this cannot be really avoided, and in a production environment display_errors will be turned off anyway. However, I am not exactly satisfied with this solution as it seems to not be very 'clean'.
You can't catch fatal exceptions in PHP. Sadly! Register a shutdown function which flushes the output buffer is all you can do. Since you already have a shutdown function then something in there is causing the problem. I would try this:
// 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();
}
... other than that I think you're stuck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With