php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #70932 Add ability to prevent handles inheritance in popen / proc_open
Submitted: 2015-11-18 03:14 UTC Modified: 2017-10-10 10:03 UTC
Votes:10
Avg. Score:4.3 ± 1.3
Reproduced:7 of 7 (100.0%)
Same Version:5 (71.4%)
Same OS:5 (71.4%)
From: speller at yandex dot ru Assigned:
Status: Open Package: Program Execution
PHP Version: 7.1.10 OS: Irrelevant
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: speller at yandex dot ru
New email:
PHP Version: OS:

 

 [2015-11-18 03:14 UTC] speller at yandex dot ru
Description:
------------
Currently, any child process started from PHP using popen(), proc_open() or exec() etc. will inherit opened file handles. This is caused by TRUE value of the bInheritHandles parameter of the CreateProcess WinAPI function.

This lead to the following issue. Example pseudocode:

strater.php
<?
$f = fopen('file.txt');
popen('php worker.php');
fclose('file.txt');
unlink('file.txt');
?>

worker.php
<?
sleep(600);
?>

If you will try to run these scripts you will get the exception on unlink('file.txt') line saying you don't have such permissions to remove the file. Because the opened file handle was inherited by the child process 'php worker.php' and even if you fclose() the starter's file handle the file can not be deleted while there is any other handle referenced to it in any other process in the system. 

So in this case the worker process do nothing in its code to lock the file, but system internals do it and the script can not prevent it. 

So I suggest to add an ability to set the bInheritHandles flag to FALSE when creating child processes to prevent the issue when child process keeps file handles implicitly.

Expected result:
----------------
The file.txt shold be deleted by the unlink() function.

Actual result:
--------------
unlink() function fail to delete file.txt with message of lack permissions.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-11-18 04:22 UTC] requinix@php.net
-Summary: Add ability to prevent hanles inheritance +Summary: Add ability to prevent handles inheritance in popen -Package: *General Issues +Package: Filesystem function related
 [2015-11-18 04:22 UTC] requinix@php.net
popen is supposed to behave like a fork. The Windows behavior mirrors the Unix behavior.
http://linux.die.net/man/3/popen

Maybe you should be using proc_open?
 [2015-11-18 05:14 UTC] speller at yandex dot ru
I tried the proc_open() function but it has the same issue - file handles are inherited from the parent process. So all files opened in the parent process at the time of the child process starting remain opened all the time while child process is running. This is an important issue if child process should work much longer than parent process.
 [2017-10-09 09:41 UTC] kelunik@php.net
-Summary: Add ability to prevent handles inheritance in popen +Summary: Add ability to prevent handles inheritance in popen / proc_open -Package: Filesystem function related +Package: Program Execution -Operating System: windows +Operating System: Irrelevant -PHP Version: 5.6.15 +PHP Version: 7.1.10
 [2017-10-09 09:41 UTC] kelunik@php.net
This issue appears on both Windows and Unix as it seems. It causes https://github.com/amphp/aerys/issues/192 and without a fix it's not possible to launch long-running child processes in any long running PHP script like an app server.
 [2017-10-10 08:43 UTC] mike@php.net
See the 'e' mode flag for fopen.
 [2017-10-10 10:03 UTC] speller at yandex dot ru
Will the 'e' fopen flag work under Windows?
 [2017-10-10 10:48 UTC] kelunik@php.net
The 'e' flag doesn't work on Windows, works only for fopen and I don't know any library that uses it, so it doesn't really help.

I think the default should be changed to use O_CLOEXEC. Another alternative is to just close all descriptors after the fork and before the exec that are not 0|1|2, at least with an option such as "inherit_handles" => false.

On Windows it's trivial to implement "inherit_handles" => false, because it's explicitly set there.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC