ExceptionHandler未捕获所有未捕获的异常

3

我已经创建了一个简单的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之后不久,将构建一个使用数据库存储数据的Session组件。
当使用APC时,会话组件设置以下内容以正确关闭会话:
register_shutdown_function('session_write_close'); 

我之前执行了一个测试,关闭了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不可用,因此我们得到了一个未捕获的异常。有没有什么办法解决这个问题?
我正在运行在Windows 7机器上使用mod_cgi的Apache 2.2上的fcgi PHP 5.3.9。
堆栈跟踪:
#   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将被关闭。然而,我对此解决方案并不完全满意,因为它似乎不是非常“干净”。


这可能不能解决你的问题,但你可以尝试通过删除空格来更正这段代码 $exception-> getFile());,使其变为 $exception->getFile()); - user895378
将有问题的代码放在try/catch中,并在抛出PDO异常时检查当前异常处理程序。也许其他组件在你不知情的情况下重置了异常处理程序? - Jon
@rdlowrey:修复它,尽管那只是我在写问题时的一个打字错误。@Jon:尝试将代码包装在try/catch中,并能够消除异常。检查了异常处理程序,仍然使用的是“ExceptionHandler”。我已经明确地将“exit()”添加到“handleException()”中,但似乎在“exit()”之后仍然会输出那些未捕获的异常! - F21
1个回答

1
您无法在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();
}

除此之外,我认为你卡住了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接