diff --git a/tests/015-stack_resources_fd.phpt b/tests/015-stack_resources_fd.phpt index 6655a00..c142282 100644 --- a/tests/015-stack_resources_fd.phpt +++ b/tests/015-stack_resources_fd.phpt @@ -10,7 +10,7 @@ $fd = fopen(__FILE__, 'r'); var_dump($fd); $int_fd = \get_fd_resource($fd); var_dump($int_fd); -var_dump(create_resource_fd($int_fd)); +var_dump(create_resource_fd($int_fd, new \stdClass)); [$zval, $fd1] = \zval_to_fd_pair($fd); var_dump($zval, $fd1); var_dump(\get_resource_fd($fd1)); diff --git a/zend/Functions.php b/zend/Functions.php index 1362d4b..205a5e3 100644 --- a/zend/Functions.php +++ b/zend/Functions.php @@ -374,28 +374,30 @@ function create_resource(CData $fd_ptr, string $type = 'stream', int $module = \ } /** - * Create `resource` from `int`, _bind_ to an **CData** `object`. - * - by way of `php_stream_fopen_from_fd()` + * Same as `get_resource_fd()`, but holds reference to an `object`. + * - This returns the static held reference in ZE `Resource` class, or creates one. * * @param integer $fd - * @param object $extra + * @param object $store * @return resource */ - function create_resource_fd(int $fd, object $extra = null) + function create_resource_fd(int $fd, object $store = null) { - return PhpStream::fd_to_zval($fd, 'wb+', false, $extra); + return PhpStream::fd_to_zval($fd, 'wb+', false, $store); } /** * Create and register `resource` from **CData** `object`, _bind_ to `int` **fd**. - * - by way of `zend_register_resource()` + * - by way of `zend_register_resource()`. + * - This will also create static held reference in ZE `Resource` class. * * @param integer $fd - * @param object $cdata + * @param object $cdata PHP `__invoke()` instance that returns `CData` + * @param string $type resource string type * @param callable $rsrc * @return resource */ - function create_resource_object(int $fd, object $cdata, callable $rsrc = null) + function create_resource_object(int $fd, object $cdata, string $type = 'stream', callable $rsrc = null) { $object_ptr = $cdata(); $object_res = \zend_register_resource( @@ -404,7 +406,7 @@ function create_resource_object(int $fd, object $cdata, callable $rsrc = null) ? function (CData $rsrc) { } : $rsrc), null, - 'stream', + $type, \ZEND_MODULE_API_NO ) ); @@ -482,6 +484,7 @@ function zval_blank(): Zval } /** + * - This returns the static held reference in ZE `Resource` class, or creates one. * @param resource $stream * @return array */ @@ -495,6 +498,7 @@ function zval_to_fd_pair($stream, string $typedef = 'php_socket_t'): array /** * Return `int` of _file descriptor_ from a **resource**, after converting into/from `php_stream` C struct. + * - This returns the static held reference in ZE `Resource` class, or creates one. * * @param resource|int $fd * @return int|uv_file `fd` @@ -510,6 +514,7 @@ function get_fd_resource($fd, string $typedef = 'php_socket_t'): int /** * Remove/free any `resource` created with `get_resource_fd()`, `get_fd_resource()`, * `get_socket_fd()`, or `zval_to_fd_pair()`. + * - This removes the static held reference from ZE `Resource` class. * * @param resource|int|Zval $fd_Int_Zval * @return void @@ -533,6 +538,7 @@ function remove_fd_resource(...$fd_Int_Zval): void /** * Returns any `resource` created with `get_resource_fd()`, `get_fd_resource()`, `get_socket_fd()`, * `create_resource_object()`, `create_resource_fd()` or `zval_to_fd_pair()`. + * - This returns the static held reference in ZE `Resource` class. * * @param integer $handle * @param boolean $get_int @@ -548,6 +554,7 @@ function resource_get_fd(int $handle, bool $get_int = true, bool $get_pair = fal /** * Return `resource` from `int` a _file descriptor_, after converting into/from `php_stream` C struct. + * - This returns the static held reference in ZE `Resource` class, or creates one. * * @param int $fd * @param string $mode @@ -561,6 +568,7 @@ function get_resource_fd($fd, string $mode = 'wb+', bool $getZval = false) /** * Return `int` of _file descriptor_ from a **socket**, after converting into/from `php_socket` C struct. + * - This returns the static held reference in ZE `Resource` class, or creates one. * * @param resource|int|\Socket $fd * @return php_socket_t|int diff --git a/zend/Types/PhpStream.php b/zend/Types/PhpStream.php index 8aaba3e..52245cf 100644 --- a/zend/Types/PhpStream.php +++ b/zend/Types/PhpStream.php @@ -87,7 +87,7 @@ public static function open_wrapper( * @param bool $getZval * @return resource|Zval|null */ - public static function fd_to_zval($fd, $mode = 'wb+', bool $getZval = false, object $extra = null) + public static function fd_to_zval($fd, $mode = 'wb+', bool $getZval = false, object $store = null) { $stream = \resource_get_fd($fd, false, true); if (\is_array($stream)) { @@ -104,8 +104,8 @@ public static function fd_to_zval($fd, $mode = 'wb+', bool $getZval = false, obj $resource = \zval_native($zval); $php_stream = \fd_type('', false); $php_stream->update($stream, true); - if (!\is_null($extra)) - $php_stream->add_object($extra); + if (!\is_null($store)) + $php_stream->add_object($store); $php_stream->add_fd_pair($fd, $resource); } catch (\Throwable $e) { diff --git a/zend/Types/Resource.php b/zend/Types/Resource.php index cc93fef..4e4dc81 100644 --- a/zend/Types/Resource.php +++ b/zend/Types/Resource.php @@ -151,12 +151,6 @@ protected function __construct(string $typedef, bool $create = true) public function free(): void { - if (!\is_null($this->gc_object)) { - $object = $this->gc_object; - $this->gc_object = null; - \zval_del_ref($object); - } - if (!\is_null($this->ze_other_ptr)) { if (\is_typeof($this->ze_other_ptr, 'struct _php_stream*')) \ze_ffi()->_php_stream_free($this->ze_other_ptr, self::PHP_STREAM_FREE_CLOSE); @@ -184,12 +178,19 @@ public function clear(int $handle): void if (isset($this->fd[$handle])) { [$fd, $res] = $this->fd[$handle]; unset($this->fd[$fd], $this->fd[(int)$res]); + static::$instances[$fd] = null; $resource = static::$instances[(int)$res]; static::$instances[(int)$res] = null; - if (\count($this->fd) === 0) + if (\count($this->fd) === 0) { \zval_del_ref($resource); + if (!\is_null($this->gc_object)) { + $object = $this->gc_object; + $this->gc_object = null; + \zval_del_ref($object); + } + } } }