背景
项目架构采用 Swoole\Http\Server
+ Yaf
实现,业务层 Yaf
若有未捕获异常配置如下:
application.dispatcher.throwException = 1
; 开启此项,如果有未捕获的异常,Yaf将会把它定向到Error controller, Error Action。
application.dispatcher.catchException = 1
业务层所有未捕获异常可在 ErrorController->ErrorAction
中处理。
解决方案是更改 Yaf
配置项 application.dispatcher.catchException = 0
,worker
中对 Yaf
层做 try{...}catch(...)
处理。
深度解析
Yaf 源码文件 yaf_dispatcher.c
中的 yaf_dispatcher_exception_handler
方法对异常做了处理: YAF_G(in_exception) = 1;
,在 PHP_RSHUTDOWN_FUNCTION
模块做的清除工作。导致 Swoole
的每个 worker
仅在进程首次可以由 ErrorController->ErrorAction
捕获异常,其他情况将导致 worker
进程异常退出。
源码解决方案:
-
yaf_dispatcher_exception_handler
方法尾部追加YAF_G(in_exception) = 0;
- 自定义清除函数,
ErrorController
中处理异常后调用$this->clear();
重置。
$ vim yaf_controller.c
PHP_METHOD(yaf_controller, clear) {
YAF_G(in_exception) = 0;
RETURN_TRUE;
}
/** {{{ yaf_controller_methods
*/
zend_function_entry yaf_controller_methods[] = {
PHP_ME(yaf_controller, render, yaf_controller_render_arginfo, ZEND_ACC_PROTECTED)
PHP_ME(yaf_controller, display, yaf_controller_display_arginfo, ZEND_ACC_PROTECTED)
PHP_ME(yaf_controller, getRequest, yaf_controller_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, getResponse, yaf_controller_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, getModuleName,yaf_controller_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, getView, yaf_controller_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, initView, yaf_controller_initview_arginfo,ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, setViewpath, yaf_controller_setvdir_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, getViewpath, yaf_controller_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, forward, yaf_controller_forward_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, redirect, yaf_controller_redirect_arginfo,ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, getInvokeArgs,yaf_controller_void_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, getInvokeArg, yaf_controller_getiarg_arginfo,ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, clear, NULL, ZEND_ACC_PUBLIC)
PHP_ME(yaf_controller, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
PHP_ME(yaf_controller, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
{NULL, NULL, NULL}
};
/* }}} */
网友评论