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

时间:2016-03-10 19:20:53

标签: php php-extension php-7 php-internals

我正在将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中,使用rsrc删除zend_hash_index_del( &EG( regular_list ), Z_RESVAL_P( 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, type为-1且ptr为NULL(在第一次调用中在zend_resource_dtor中分配)。当我在PHP脚本中调用get_resources()时,我得到rsrc及其ID UNKOWN,其中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'

1 个答案:

答案 0 :(得分:3)

简短的回答是资源会在请求关闭时被删除,特别是在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清理时没有泄漏。即使您要从哈希中手动删除项目,我也不认为底层内存会立即被释放。

相关问题