Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExceptionHandler not catching all uncaught exceptions

Tags:

exception

php

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'.

like image 515
F21 Avatar asked Feb 22 '26 14:02

F21


1 Answers

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

like image 70
Precastic Avatar answered Feb 25 '26 04:02

Precastic



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!