I\'m a little puzzled if I can spare the fclose
command by just unsetting the variable that carries the handle?
$handle = fopen($file);
...
fclo
PHP docs hint that all resources with no remaining references are "freed", I assume for file handles this would include closing the file.
Simple test case:
$f = fopen("test.php", "r");
if (!flock($f, LOCK_EX)) {
print("still locked\n");
exit;
}
unset($f);
sleep(5);
print("goodbye\n");
(I've saved this as test.php
, so it is locking itself; might need to change the filename in the fopen()
to some existing file otherwise)
Run the script twice within 5 seconds; if you get "still locked", then apparently unsetting the handle did not release the lock. In my test, I did not get "still locked", so apparently unsetting the handle at least releases the lock, though it would seem silly to release locks upon garbage collection, but not close the file.
Thanks to the reference-counting system introduced with PHP 4's Zend Engine, a resource with no more references to it is detected automatically, and it is freed by the garbage collector.
Consider the implications of this. It's safe to assume that all traces of the variable are gone after the garbage collection. In other words, at the end of PHP's execution, if PHP is not still tracking the reference, how would it close it? Thus, it seems fairly logical that it would close it when the garbage collector eats it.
This is a bad logical argument though because it assumes that garbage collections happens either immediately or shortly after unset and that PHP does not keep hidden references to variables that no longer exist in user land.
A more compelling case though could be a potential behavioural flaw if PHP did not close file handles when they go out of scope. Consider a daemon of some kind that opens lots of files. Now consider if fclose is never called. Instead, variables are allowed to fall out of scope or unset is explicitly called on them.
If these file handles were not closed, this long running daemon would run out of file handles.
Potentially behavior specific test script:
<?php
$db = mysql_connect(...);
if ($db) {
echo "Connected\n";
sleep(5); //netstat during this just for paranoia
unset($db);
echo "Unset\n";
sleep(5); //netstat during this and the connection is closed
}
On both Windows 7 and Debian 6, the connection has been closed after the unset.
Obviously though, this only proves that on my specific machines with my specific PHP version will this work. Has no meaning on file handles or the like :).
Am searching the PHP source now for hard proof
unset($handle)
will destroy the $handle
variable, but it won't close the file being pointed by $handle
. You still need to call fclose()
to close the file.
some research:
fclose
makes $handle
to be resource(5) of type (Unknown)
while
unset
makes it NULL
.
and after fclose
php consumes 88 bytes of memory more.
so: they are different =)