【问题标题】:ExceptionHandler not catching all uncaught exceptionsExceptionHandler 没有捕获所有未捕获的异常
【发布时间】:2012-01-09 01:43:11
【问题描述】:

我已经构建了一个简单的 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 上将 php 5.3.9 作为 fcgi 运行。

堆栈跟踪:

#   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());
  • 将有问题的代码包装在 try/catch 中,并在抛出 PDO 异常时检查当前异常处理程序是什么。也许其他一些组件会在你背后重置异常处理程序?
  • @rdlowrey:修复它,虽然这只是我写问题时的一个错字。 @Jon:尝试将代码包装在 try/catch 中,并且能够使异常静音。检查异常处理程序,它仍然在使用ExceptionHandler。我已将exit() 明确添加到handleException() 中,但在exit() 之后似乎仍在输出那些未捕获的异常!

标签: php exception-handling


【解决方案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();
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-16
    • 2020-06-05
    • 2017-12-07
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多