Swoole + Yaf 解决统一处理业务层未捕获异常Bug

2019-08-22  本文已影响0人  codezm
背景

项目架构采用 Swoole\Http\Server + Yaf 实现,业务层 Yaf 若有未捕获异常配置如下:

application.dispatcher.throwException = 1
; 开启此项,如果有未捕获的异常,Yaf将会把它定向到Error controller, Error Action。
application.dispatcher.catchException = 1

业务层所有未捕获异常可在 ErrorController->ErrorAction 中处理。

解决方案是更改 Yaf 配置项 application.dispatcher.catchException = 0worker 中对 Yaf 层做 try{...}catch(...) 处理。

深度解析

Yaf 源码文件 yaf_dispatcher.c 中的 yaf_dispatcher_exception_handler 方法对异常做了处理: YAF_G(in_exception) = 1;,在 PHP_RSHUTDOWN_FUNCTION 模块做的清除工作。导致 Swoole 的每个 worker 仅在进程首次可以由 ErrorController->ErrorAction 捕获异常,其他情况将导致 worker 进程异常退出。

源码解决方案:

$ 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}
};

/* }}} */
上一篇 下一篇

猜你喜欢

热点阅读