Yaf的Action中Dispatch导致Segmentation fault

PHPABC PHP开发 1,068 次浏览 , 没有评论

首先,这个问题是在Yaf群偶然看到的,这些小伙儿不折腾不畅快,今天闲来,扫了一下代码,得出结论。

其次,另外一个观点是,工具在运用时一定要清楚其原理,不然就是自己跳坑了没有人救的。

先简单明了看一下,在基于Yaf的PHP代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
use Yaf/Dispatcher;
use Yaf/Controller_Abstract;

final class IndexController extends Controller_Abstract
{

public function init()
{

// 无
}

public function indexAction()
{

$request = new Yaf/Request/Simple('API', 'index', 'index', 'simple');
Dispatcher::getInstance()->dispatch($request);
$this->_view->assign('displayWelcome', 1);
$this->_view->assign('hello', 'hello world!');
}

public function simpleAction()
{

echo 'xudianyang';
}
}

在默认的indexAction中,我创建了一个Yaf/Request/Simple的请求对象$request,参数的意思是请求Index模块和Index控制器的Simple动作,这里需要注意的是,如果你将请求设置为和当前action的路由参数相同,那么你将进入死循环,都不用大拇指想就知道。然后调用派遣器Dispatcher的dispatch方法,进行路由分发。

结合源码,我把这个程序的流程图画一下:

Yaf的Action中Dispatch导致Segmentation fault

从图中可以看出,在“新一轮分发”的过程中,任何一个环节出现问题,或者exit,return都不会产生程序崩溃。比如,simpleAction方法这样写:

1
2
3
4
5
public function simpleAction()
{

echo 'xudianyang';
exit;
}

再比如:simple方法对应的模板文件views/index/simple.phtml不存在,也不会生产Segmentation fault。

产生段错误的原因在图中说得也很明显,指针引用不再可用,因为新一轮分发是调用了Dispatcher::getInstance()->dispatch($request);此方法会重置Yaf/Dispatcher单实例的$_request属性。

通过gdb调试core文件也可以得出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(gdb) bt
#0 0x083d58d4 in zend_std_read_property (object=0xb777c020, member=0xb73f8938, type=3, key=0x0)
at /home/vagrant/php-5.4.31/Zend/zend_object_handlers.c:431
#1 0x083b4508 in zend_read_property (scope=0xa392cb8, object=0xb777c020, name=0xcb64c6 "module", name_length=6, silent=1 '/001')
at /home/vagrant/php-5.4.31/Zend/zend_API.c:3859
#2 0x00c96c85 in yaf_dispatcher_fix_default (dispatcher=0xb778143c) at /home/vagrant/yaf-2.3.2/yaf_dispatcher.c:236
#3 yaf_dispatcher_dispatch (dispatcher=0xb778143c) at /home/vagrant/yaf-2.3.2/yaf_dispatcher.c:927
#4 0x00c91bd6 in zim_yaf_application_run (ht=0, return_value=0xb7799fcc, return_value_ptr=0x0, this_ptr=0xb777a140,
return_value_used=0) at /home/vagrant/yaf-2.3.2/yaf_application.c:468
#5 0x0841f5d4 in zend_do_fcall_common_helper_SPEC (execute_data=<value optimized out>)
at /home/vagrant/php-5.4.31/Zend/zend_vm_execute.h:643
#6 0x084137a6 in execute (op_array=0xb777a408) at /home/vagrant/php-5.4.31/Zend/zend_vm_execute.h:410
#7 0x083b1c6e in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/vagrant/php-5.4.31/Zend/zend.c:1315
#8 0x08357706 in php_execute_script (primary_file=0xbfb72338) at /home/vagrant/php-5.4.31/main/main.c:2502
#9 0x0845c1cb in main (argc=6, argv=0xbfb72494) at /home/vagrant/php-5.4.31/sapi/fpm/fpm/fpm_main.c:1933

最后,其实分析这个只是熟悉一下Yaf的分发策略及其源码。另外,想要在一个action中执行另外一个action,其实鸟哥已经考虑了,通过Yaf_Controller_Abstract::forward就可以了。我们在实际应用中,不要异想天开,乱来!

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Go