[php-src] Issue #12656: fclose() does not set file ressource to NULL causing error 500 on Siteground host. Combination of possible bug and hitting
ressource limits.
| From: | rene-hermenau | Date: | Sun, 12 Nov 2023 15:29:17 +0000 |
| Subject: | [php-src] Issue #12656: fclose() does not set file ressource to NULL causing error 500 on Siteground host. Combination of possible bug and hitting ressource limits. |
||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-245793@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/12656
Author: rene-hermenau
### Description
Found a possible bug in fclose() that appears when hitting some ressource limits like having open
too many file ressources. The issue currently appears only the Siteground hosting provider when
opening and closing a few thousand files, quickly one after another. (Not opening them
concurrently!)
Due to the nature of the issue I am not able to provide you code that makes it fully reproduceable
but I will provide the code that fails and the solution that works for us:
I've simplified the code but essentially these basic functions fail when opening and closing
many files quickly:
````
for ($i = 0; $i < 40000; $i++) {
$destFile = $dirname . '/test' . $i . '.text';
$fp = fopen($destFile, 'ab');
fwrite($fp, 'test');
fclose($fp);
}
````
You can also use file_put_contents() instead of fopen, fwrite and fcose and the result will be the
same, a fatal error without any error message during execution!
Setting the file ressource to null after closing it will make it pass.
So this code works:
````
for ($i = 0; $i < 40000; $i++) {
$destFile = $dirname . '/test' . $i . '.text';
$fp = fopen($destFile, 'ab');
fwrite($fp, 'test');
fclose($fp);
$fp = null; // the only difference
}
````
Unfortunately the failed system throws a fatal error 500 without actual throwing an error message so
we can not provide exact reason why it fails but it looks like a ressource problem in combination
with a bug .
A little bit more about the application where this code is used and to proof that we have no
fundamental flaw in the rest of our code base:
We use that code for a heavily unit tested backup application that works on more than 150.000 active
websites with all types of php versions higher than 7.0 up to 8.3 and all types of different hosting
providers without any issues. The specific problem happens only one one of these clients and
currently only on the siteground hosting platform and with a larger backup file that has multiple
GB's, so we think its pure coincidence we found that problem.
I think it is both (a bug and a resource problem). Because freeing the resource on fclose()
immediately may not be required but on a single function like file_put_contents and
file_get_contents which doesn't provide access to internal resource it should be freed
automatically immediately.
I digged a little bit into the php source and found many occurances of:
````
php_stream_close(stream);
stream = NULL;
````
while many other usages only call
````
php_stream_close(stream);
`````
without setting stream to null.
I am not sure if this inconsistency is intended or is there a reason to not always set stream to
null **after** closing it?
I am curious if you have an idea what goes wrong here.
### PHP Version
php 8.1.25
### Operating System
ubuntu 20.04