Skip to content

Regression: the fix for #8575 makes it impossible to intentionally close std handles #8827

Closed
@fds242

Description

@fds242

Description

On Unix-like systems, closing a std file handle has the useful property that the next file handle you open will inherit its place. This provides a very simple and effective way to reroute stdin/stdout/stderr during run time.

This has historically also been possible through PHP-CLI scripts, and as a result has become common practice, oft-repeated boilerplate code for using pcntl_fork() in particular, where it is almost always desirable for the forked children to stop using the parent's stdin/stdout/stderr.

This used to be as simple as, for example:

<?php
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$in = fopen('/dev/null', 'r');
$out = fopen('stdout-now-goes-here.txt', 'a');
$err = fopen('stderr-now-goes-here.txt', 'a');

The fix for an unrelated issue in #8575, and unfortunately included in both PHP 8.1.7 and PHP 8.0.20, also makes it impossible for PHP code to willfully close the std file handles anymore. This breaks a whole swath of past code that depended on this functionality, a rather unwelcome and unexpected change for minor releases.

Here's a test:

--TEST--
std handles can be deliberately closed
--SKIPIF--
if (php_sapi_name() != "cli") {
	die("skip CLI only");
}
if (substr(PHP_OS, 0, 3) == 'WIN') {
	die("skip not for Windows");
}
--FILE--
<?php
fclose(STDERR);
var_dump(@fopen('php://stderr', 'a'));
?>
--EXPECT--
bool(false)

With PHP 8.1.7 or 8.0.20 this now results in the following output instead:

resource(5) of type (stream)

3v4l link: https://3v4l.org/OgYWN

PHP Version

PHP 8.1.7

Operating System

Linux, macOS

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions