php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #75868 is_resource() gettype() get_resources() inconsistent result on closed resource
Submitted: 2018-01-24 14:31 UTC Modified: 2021-06-10 15:25 UTC
Votes:6
Avg. Score:4.0 ± 1.0
Reproduced:5 of 5 (100.0%)
Same Version:1 (20.0%)
Same OS:1 (20.0%)
From: bobonov at gmail dot com Assigned:
Status: Re-Opened Package: Variables related
PHP Version: 7.2.1 OS: Ubuntu 17.10
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: bobonov at gmail dot com
New email:
PHP Version: OS:

 

 [2018-01-24 14:31 UTC] bobonov at gmail dot com
Description:
------------
Checking the closed resource with:
gettype() return resource (closed)
get_resources() list it as resource
is_resource() return false.

There is an ancient Bug #42797 (php 4.3.6) that is relevant to this bug

Test script:
---------------
<?php
$a = fopen('http://www.google.com', 'r');
echo "$a : the type is " . gettype($a)."\n";  // resource
var_dump(is_resource($a)); // true
print_r(get_resources());

fclose($a);
echo "$a : the type is " . gettype($a)."\n";  // resource closed
var_dump(is_resource($a)); // false
print_r(get_resources());


Expected result:
----------------
I expect is_resource() to return true since  get_resources() and gettype() see the var as resource

Actual result:
--------------
Resource id #6 : the type is resource
bool(true)
Array
(
    [1] => Resource id #1
    [2] => Resource id #2
    [3] => Resource id #3
    [4] => Resource id #4
    [6] => Resource id #6
)
Resource id #6 : the type is resource (closed)
bool(false)
Array
(
    [1] => Resource id #1
    [2] => Resource id #2
    [3] => Resource id #3
    [4] => Resource id #4
    [6] => Resource id #6
)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-01-25 13:41 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2018-01-25 13:41 UTC] cmb@php.net
> Checking the closed resource with:
> is_resource() return false.

Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

This is documented[1] behavior:

| is_resource() is not a strict type-checking method: it will
| return FALSE if var is a resource variable that has been closed.

[1] <http://www.php.net/manual/en/function.is-resource.php#refsect1-function.is-resource-notes>
 [2018-01-25 15:16 UTC] bobonov at gmail dot com
In the title I reported it as "inconsistent result on closed resource".

I know that is the intend behavior, as clearly reported in the documentation, but anyway it is a bug.

While 2 function report it as still a resource, is_resource() say is not a resource.

Yes gettype() report it as "resource (closed)" which in my opinion is a strange type since closed denote a status not a variable type, or at least resource type

We have 3 different result checking the same variable
is_resource() say is a resource
gettype() report "resource (closed)" (which in php does not exist)
get_resources() which still list it as resource

To make more clear the inconsistent type checking by different function for a resource I made a bit more complete script (in which you can see that var_dump() get_resource_type() still see closed one as resource).
In particular get_resource_type() give  a warning when used to test a non resource type.
"PHP Warning:  get_resource_type() expects parameter 1 to be resource, string given"
So if even the runtime see closed resource as resource... it is a resource

<?php
function testResource($a) {
    echo "$a\n";
    echo "gettype(): " . gettype($a)."\n";
    echo "is_resource():";
    var_dump(is_resource($a));
    echo "get_resource_type(): " . get_resource_type ( $a )."\n";
    echo "get_resources():";
    print_r(get_resources());
    echo "var_dump():";
    var_dump($a);
}

$a = fopen('http://www.google.com', 'r');
echo "OPEN resource\n";

testResource($a);
fclose($a);
echo "\n\n\nCLOSED resource\n";

testResource($a);
?>

this script will produce the following result:
OPEN resource
Resource id #6
gettype(): resource
is_resource():bool(true)
get_resource_type(): stream
get_resources():Array
(
    [1] => Resource id #1
    [2] => Resource id #2
    [3] => Resource id #3
    [4] => Resource id #4
    [6] => Resource id #6
)
var_dump():resource(6) of type (stream)


CLOSED resource
Resource id #6
gettype(): resource (closed)
is_resource():bool(false)
get_resource_type(): Unknown
get_resources():Array
(
    [1] => Resource id #1
    [2] => Resource id #2
    [3] => Resource id #3
    [4] => Resource id #4
    [6] => Resource id #6
)
var_dump():resource(6) of type (Unknown)


Probably the correct output (to make everything consistent and logic) for a closed resource should be:
gettype(): resource
is_resource():bool(true)
get_resource_type(): closed
var_dump():resource(6) of type (closed)

All "resource provider" should change a resource type to closed when *close() is called.
 [2018-01-25 15:19 UTC] spam2 at rhsoft dot net
and how do you imagine is_resource() to be useful when it answers yes ona closed one which can't be used in the next line?

changing that would be a regression and break existing code for no purpose
 [2018-01-25 16:00 UTC] cmb@php.net
-Status: Not a bug +Status: Re-Opened -Assigned To: cmb +Assigned To:
 [2018-01-25 16:00 UTC] cmb@php.net
> I know that is the intend behavior, as clearly reported in the
> documentation, but anyway it is a bug.

If you insist.
 [2018-01-26 08:09 UTC] bobonov at gmail dot com
I do not say that my proposal is correct, probably is deeply wrong.
I only see it as the more logical (and probably I'm wrong again). And eventually being the more logical does not imply that is the best solution.
A different solution would move the problem in another function.

I say that there is a general consistency problem of the results from different function.
So if leaving is_resource() untouched is the best solution (why not) the issue is still there.

Then if you think that the problem (because I hope you do not deny that there is a consistency problem) is not a problem, then close the bug.
 [2018-01-26 15:16 UTC] salsi at icosaedro dot it
For the record, closed resources are "unknown type"s (or "resource (closed)" since PHP 7.2.0) according to gettype() and are not resources at all according to is_resource(), but these values are still reported as resource in the stack trace, for example:

<?php
// Set a safe environment:
error_reporting(-1);

// Maps errors to ErrorException.
function my_error_handler($errno, $message)
{ throw new ErrorException($message); }

set_error_handler("my_error_handler");

$f = fopen(__FILE__, "r");
fclose($f);
fclose($f); # double close -- here fails, as expected
?>

displays:

PHP Fatal error:  Uncaught exception 'ErrorException' with message 'fclose(): 5 is not a valid stream resource' in C:\Users\UmbertoSalsi\Desktop\php\resource.php:7
Stack trace:
#0 [internal function]: my_error_handler(2, 'fclose(): 5 is ...', 'C:\\Users\\Umbert...', 13, Array)
#1 C:\Users\UmbertoSalsi\Desktop\php\resource.php(13): fclose(Resource id #5)
#2 {main}
  thrown in C:\Users\UmbertoSalsi\Desktop\php\resource.php on line 7
Fatal error: Uncaught exception 'ErrorException' with message 'fclose(): 5 is not a valid stream resource' in C:\Users\UmbertoSalsi\Desktop\php\resource.php:7
Stack trace:
#0 [internal function]: my_error_handler(2, 'fclose(): 5 is ...', 'C:\\Users\\Umbert...', 13, Array)
#1 C:\Users\UmbertoSalsi\Desktop\php\resource.php(13): fclose(Resource id #5)
#2 {main}
  thrown in C:\Users\UmbertoSalsi\Desktop\php\resource.php on line 7

Note the "fclose(): 5 is not a valid stream resource" and then the following "fclose(Resource id #5)" above: it's all a bit confusing.
I still do not understand what a program should do to safely detect the type of a value at runtime.
 [2021-06-10 15:25 UTC] cmb@php.net
-Type: Bug +Type: Documentation Problem
 [2021-06-10 15:25 UTC] cmb@php.net
Okay, were are we?   We cannot change the behavior of
is_resource() for stated reasons; we will not change the behavior
of gettype() for BC reasons; we should document that
get_resources() also includes closed resources in its return value
("all currently active resources" is indeed confusing).  We should
also document the concept of "closed resources" on the resources
page.

Other than that, we should convert all resources to objects; this
work has already begun[1], but is still work in progress for time
and BC reasons.

[1] <https://www.php.net/manual/en/migration80.incompatible.php#migration80.incompatible.resource2object>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 23:01:27 2024 UTC