php / php-src

The PHP Interpreter
https://www.php.net
Other
37.83k stars 7.71k forks source link

File descriptors / some procfs entries not openable by php #9551

Open SpencerMalone opened 1 year ago

SpencerMalone commented 1 year ago

Description

The following code:

<?php
file_put_contents("/proc/1/fd/1", "hi");

Resulted in this output:

file_put_contents(/proc/1/fd/1): failed to open stream: No such file or directory

But I expected this output instead:

2

This is highly impactful for containerized PHP environments. php-fpm has unique workarounds that they've utilized, and in the past the fd stream wrapper was implemented to support managing the current process's file descriptors, but if you are in a different SAPI and/or utilize forking or execing to other PHP scripts, stdout in a docker container quickly turns into a black hole in terms of container logging, where it's expected that all logs are sent to the PID 1 stdout/err. See: https://bugs.php.net/bug.php?id=53465 where they hypothesize this is due to PHP incorrectly attempts to dereference the pseudo-symlink before opening it. The hypothesis makes sense to me. It'd be nice to see this fixed for all file descriptors.

PHP Version

7.4

Operating System

Centos 7.9

SpencerMalone commented 1 year ago

Some examples where previous people have done some hacky things to try and sidestep this issue, although all of these come with major tradeoffs: https://github.com/bakins/socket2stdout - This is only not a great option due to the fact that socket creation can be interrupted by common signals (for example: apache2 graceful restarts or stops) https://github.com/relaxart/monolog-docker-handler/blob/master/src/DockerMonologHandler.php#L50

cmb69 commented 1 year ago

Did you try https://pecl.php.net/package/dio?

Also note that PHP 7.4 is no longer actively supported; I presume, though, that the behavior with more recent versions is (basically) the same.

SpencerMalone commented 1 year ago

I have not tried dio, I did look at it beforehand, but backed away after seeing it was not a core extension. I'm not against giving it a try and reporting back as a workaround.

cmb69 commented 1 year ago

I'm not against giving it a try and reporting back as a workaround.

Yeah, please try dio. I'm not convinced that we should add support for arbitrary file descriptors.

SpencerMalone commented 1 year ago

I guess I'm unclear on why it would be desirable to avoid that in core PHP.

So, good news: Dio works

Bad news: It only has beta versions published, which makes me very reluctant to utilize, and you can't "cross the streams"/ utilize dio resources with "normal" stream resource functions. This is mostly impactful because it makes working with common logging packages (such as monolog) a much heavier lift. Granted, it's technically possible, but it's really painful.

cmb69 commented 1 year ago

I guess I'm unclear on why it would be desirable to avoid that in core PHP.

That might open up a can of worms. There may have been more reasons than portability why @cataphract chose to implement the php://fd stream wrapper. I'm not saying that we must not support arbitrary file descriptors, but that needs closer investigation.

It only has beta versions published, which makes me very reluctant to utilize

@remicollet, any plans to release a stable dio version in the near future?

and you can't "cross the streams"/ utilize dio resources with "normal" stream resource functions

For a long time, dio offers dio.raw:// stream wrappers (which are not documented); if these can be used to access /proc/1/fd/1 etc., it should be possible to use the standard stream functions.

arnaud-lb commented 1 year ago

@SpencerMalone does it happen in some specific conditions?

I've tried reproducing it with this docker file, with no luck:

docker build -t gh9551 .
docker run -ti --rm gh9551:latest php -r 'file_put_contents("/proc/1/fd/1", "hi");'