编程语言
首页 > 编程语言> > PHP 7如何从常规列表中删除资源?

PHP 7如何从常规列表中删除资源?

作者:互联网

我正在将php扩展名升级到php 7,并且我想使用zend_register_resource删除已在常规列表中注册的资源,稍后再使用zend_list_close关闭该资源.关闭函数如下所示:

    PHP_FUNCTION(myFunc_cleanAndExit)
    {
     zval* rsrc = NULL;
     ...
     int res = zend_parse_parameters(ZEND_NUM_ARGS() , "r", &rsrc );
     if (res == FAILURE)
     {
        //handle it
     }
     ...
     zend_fetch_resource(Z_RES_P(rsrc), ./other args/..)
     ...
     zend_list_close(Z_RES_P(rsrc));
     ...
     }

最初在PHP 5中,使用zend_hash_index_del(& EG(regular_list),Z_RESVAL_P(rsrc))删除了rsrc,因此,如果两次调用此函数,则zend_parse_parameter返回FAILURE,因为该资源已从常规列表中删除并且不存在.

在PHP7中,zend_list_close调用zend_resource_dtor(rsrc refcount为2(为什么在资源注册后为1递增?),然后清除rsrc占用的所有内存.但是,有趣的是,当我们这样两次调用它时:

    myFunc_cleanAndExit($var-rsrc);
    myFunc_cleanAndExit($var-rsrc);

第二次zend_parse_parameter不返回FAILURE(因为尚未从常规列表中删除资源),并且在解析后rsrc的refcount增加到3,类型为-1并且ptr为NULL(在第一个调用中的zend_resource_dtor).当我在PHP脚本中调用get_resources()时,我得到了带有其ID和类型UNKOWN的rsrc,在PHP5中rsrc变为NULL.这是我的问题:

1-什么时候从常规列表中删除资源? (如果我使用zend_hash_index_del从常规列表中手动将其删除,则会在zend_alloc中中断)

2-关闭一次后是否可以将资源激活为UNKOWN类型?不吃光记忆吗?如果不是,我应该怎么做才能将其设置为NULL?

3-当我注册资源并检查其引用计数时,它是1,但是当我调用关闭函数时,在zend_parse_parameter之后,引用计数增加了,为什么?

谢谢

示例PHP脚本:

    <?php
    $var_rsrc = myFunc_startUp();
    var_dump($var_rsrc); // resource(2) of type 'MyFunc'
    myFunc_cleanAndExit($var_rsrc);
    var_dump($var_rsrc); // resource(2) of type 'UNKOWN' (originally this was  NULL)
    myFunc_cleanAndExit($var_rsrc);
    var_dump($var_rsrc); // resource(2) of type 'UNKOWN'

解决方法:

简短的答案是资源在请求关闭时被删除,特别是在zend_hash_graceful_reverse_destroy中.您还应该检查zend_fetch_resource的返回值,因为它将为被破坏的资源返回NULL(并发出警告).

我认为您所描述的一切都是正常的,包括zend_parse_parameters成功地解析了先前被破坏的资源.下面的程序表现出完全相同的行为:

<?php
$r = popen('ls', 'r');
echo fgets($r);
pclose($r);
var_dump(get_resources());
pclose($r);

您的资源的引用计数为2,因为SEND_VAR操作码(即,将参数传递给函数)会将其ZVAL_COPY传递给arglist,这会增加引用计数. (稍后在zend_vm_stack_free_args中取消引用.)

关于内存使用情况,我不必担心资源耗尽内存.我们已经知道它不会泄漏,因为它会在RSHUTDOWN中被清理.即使您要手动从哈希中删除该项目,我也不认为可以保证立即将底层内存释放.

标签:php-internals,php-extension,php-7,php
来源: https://codeday.me/bug/20191118/2032133.html