Swoole中参数持久化以及给闭包对象引用加一的作用?
在阅读Swoole
定时器源码的时候,php_swoole_timer_add
里面:
发现如果是调用了timer::after
接口的话,那么话进行参数持久化的操作:
sw_zend_fci_params_persist(&fci->fci);
如果是调用了timer::tick
的话,就不需要进行参数持久化的操作。
并且,最后还调用了sw_zend_fci_cache_persist
来对闭包进行引用计数加一的操作。
我想知道为什么需要做这两个操作?如果不做这两个操作,会触发什么Bug
呢?能否用一段完整的PHP
代码来触发一下这个Bug
呢?并且解释一下为什么会触发Bug
。我想看看差异在哪,以及什么时候需要调用这两个函数。
目前,我写了一段简单的脚本:
<?php
namespace Swoole;
$str = "test";
Timer::after(1000, function() use ($str){
echo "timeout, $str\n";
});
当我注释掉sw_zend_fci_cache_persist(&fci->fci_cache);
的时候,会在PHP
协程入口函数里面进入ZEND_INTERNAL_FUNCTION
这个分支:
else /* ZEND_INTERNAL_FUNCTION */
{
ZVAL_NULL(retval);
call->prev_execute_data = NULL;
call->return_value = NULL; /* this is not a constructor call */
execute_internal(call, retval);
zend_vm_stack_free_args(call);
}
然后报Segmentation fault
错误。如果不注释掉sw_zend_fci_cache_persist(&fci->fci_cache);
,那么就可以顺利的进入ZEND_USER_FUNCTION
分支:
if (EXPECTED(func->type == ZEND_USER_FUNCTION))
{
ZVAL_UNDEF(retval);
// TODO: enhancement it, separate execute data is necessary, but we lose the backtrace
EG(current_execute_data) = NULL;
#if PHP_VERSION_ID >= 70200
zend_init_func_execute_data(call, &func->op_array, retval);
#else
zend_init_execute_data(call, &func->op_array, retval);
#endif
zend_execute_ex(EG(current_execute_data));
}
但是我不知道其中的原因。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论