php中的error_handler

本文探讨了PHP中错误和异常处理的内部机制,包括error_handler和exception_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[0] = &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); }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值