|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2014-08-26 07:59 UTC] jille at hexon dot cx
Description: ------------ proc_open leaks file descriptors when leaving via the exit_fail label. There is some code to clean them up, but it is only executed when fork() fails instead of opening one of the descriptors. References: https://github.com/php/php-src/blob/c3e3c98/ext/standard/proc_open.c#L512 (goto) https://github.com/php/php-src/blob/c3e3c98/ext/standard/proc_open.c#L952 (label) https://github.com/php/php-src/blob/c3e3c98/ext/standard/proc_open.c#L852 (fork failed) Test script: --------------- <?php $descr = array( 0 => array('file', '/dev/null', 'r'), 1 => array('file', '/nonexistent', 'r'), ); for($i = 0; 1025 > $i; $i++) { $ph = proc_open('true', $descr, $pipes); } ?> PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 15:00:01 2025 UTC |
Confirmed that this bug still stands. A test which shows the failure directly: <?php // This test requires a /dev/fd filesystem (OS X for example) to show the error. // There should only be 4 descriptors (stdin, stdout, stderr, readdir of /dev/fd) open after the failed proc_open(). proc_open("/bin/true", [0 => ['pipe', 'r'], 1 => ['INVALID']], $pipes); print_r(scandir("/dev/fd")); ?> Correct fix is to move this code from the fork() failure case to the error_exit case: for (i = 0; i < ndesc; i++) { close(descriptors[i].childend); if (descriptors[i].parentend >= 0) close(descriptors[i].parentend); } (Please note - the fork() failure case does not check >= 0, which can cause a leaked descriptor if stdin was closed before proc_open() was called.)