From: jdolecek at NetBSD dot org Operating system: Any UNIX-like, Netware PHP version: 5.1.4 PHP Bug Type: Unknown/Other Function Bug description: proc_open() closes stdin on fork() failure
Description: ------------ The block spawning the child process for both Netware and UNIX-like OS contains this block in failure case: if (child < 0) { /* failed to fork() */ /* clean up all the descriptors */ for (i = 0; i < ndesc; i++) { close(descriptors[i].childend); close(descriptors[i].parentend); } ... } parentend is filled only for pipes, for 'file' handles it's not filled, and left '0' as initialized by memset() in proc_open.c line 537. So, if proc_open() was called with descriptorspec using 'file' and the fork() call fails, this results in closing descriptor 0. Quick fix is to only close parentend if it's non-zero, such as: --- ext/standard/proc_open.c.orig 2006-05-28 21:51:09.000000000 +0200 +++ ext/standard/proc_open.c @@ -796,7 +796,8 @@ PHP_FUNCTION(proc_open) /* clean up all the descriptors */ for (i = 0; i < ndesc; i++) { close(descriptors[i].childend); - close(descriptors[i].parentend); + if (descriptors[i].parentend) + close(descriptors[i].parentend); } php_error_docref(NULL TSRMLS_CC, E_WARNING, "procve failed - %s", strerror(errno)); goto exit_fail; @@ -863,7 +864,8 @@ PHP_FUNCTION(proc_open) /* clean up all the descriptors */ for (i = 0; i < ndesc; i++) { close(descriptors[i].childend); - close(descriptors[i].parentend); + if (descriptors[i].parentend) + close(descriptors[i].parentend); } php_error_docref(NULL TSRMLS_CC, E_WARNING, "fork failed - %s", strerror(errno)); Reproduce code: --------------- It's necessary to setup process limit via ulimit so that running the php script gets last allowed slot: > echo test > tst > ulimit -p `pgrep -u "\`id -u\`" | wc -l` > php script.php < tst script.php: <?php $p = proc_open("echo hello", array(0 => array('file', '/dev/null', 'r'), 1 => array('pipe', 'r')), $pipes1); echo file_get_contents("php://stdin")."\n"; Expected result: ---------------- PHP Warning: proc_open(): fork failed - Resource temporarily unavailable in /usr/home/dolecek/tmp/proc3.php on line 4 test Actual result: -------------- PHP Warning: proc_open(): fork failed - Resource temporarily unavailable in /usr/home/dolecek/tmp/proc3.php on line 4 -- Edit bug report at http://bugs.php.net/?id=37619&edit=1 -- Try a CVS snapshot (PHP 4.4): http://bugs.php.net/fix.php?id=37619&r=trysnapshot44 Try a CVS snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=37619&r=trysnapshot52 Try a CVS snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=37619&r=trysnapshot60 Fixed in CVS: http://bugs.php.net/fix.php?id=37619&r=fixedcvs Fixed in release: http://bugs.php.net/fix.php?id=37619&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=37619&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=37619&r=needscript Try newer version: http://bugs.php.net/fix.php?id=37619&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=37619&r=support Expected behavior: http://bugs.php.net/fix.php?id=37619&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=37619&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=37619&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=37619&r=globals PHP 3 support discontinued: http://bugs.php.net/fix.php?id=37619&r=php3 Daylight Savings: http://bugs.php.net/fix.php?id=37619&r=dst IIS Stability: http://bugs.php.net/fix.php?id=37619&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=37619&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=37619&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=37619&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=37619&r=mysqlcfg