shuijingping 发表于 2017-3-27 06:02:02

php中的error_handler

  一般我们为了捕获php的错误,需要自己设置error_handler,但是,如果error_handler里出错了,可能会形成递归调用。事实上这个问题根本不存在,因为php在出错以后调用了zend_error函数,然后这个函数里会判断EG(user_error_handler)是否存在,如果存在则用call_user_function_ex来调用用户方法,而在此之前,它会先将EG(user_error_handler)设置为null,这样一来如果出错的话,则不会递归进入call_user_function_ex了。
  具体代码如下:
           orig_user_error_handler = EG(user_error_handler);EG(user_error_handler) = NULL;
  exception_handler的实现却不同,因为exception其实是一个顺着栈往上传递的,因此对它的处理一定得在最上层,所以我们可以看到zend_execute_scripts里对exception进行了处理。在execute开始之前一定先要判断有没有exception,如果有则直接退出,不停地这样子退栈。而set_exception_handler的用户自定义函数最终会被call_user_function_ex调用,调用之后如果调用失败了,它会检查有没有EG(exception),如果有,则转到zend_exception_error,这个是默认实现,换句话说,也不会递归。
  具体的代码如下:
   zend_execute(EG(active_op_array) TSRMLS_CC);if (EG(exception)) {if (EG(user_exception_handler)) {zval *orig_user_exception_handler;zval ***params, *retval2, *old_exception;params = (zval ***)emalloc(sizeof(zval **));old_exception = EG(exception);EG(exception) = NULL;params = &old_exception;orig_user_exception_handler = EG(user_exception_handler);if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {if (retval2 != NULL) {zval_ptr_dtor(&retval2);}    } else {if (!EG(exception)) {EG(exception) = old_exception;}    zend_exception_error(EG(exception) TSRMLS_CC);}
页: [1]
查看完整版本: php中的error_handler