ID: 37619 User updated by: jdolecek at NetBSD dot org Reported By: jdolecek at NetBSD dot org -Status: Feedback +Status: Open Bug Type: Unknown/Other Function Operating System: Any UNIX-like, Netware PHP Version: 5.1.4 New Comment:
I think bash uses ulimit -u rathern then ulimit -p for max user processes (I've used ksh). Previous Comments: ------------------------------------------------------------------------ [2006-05-31 18:26:11] [EMAIL PROTECTED] Could you please provide a more portable reproduce case? [EMAIL PROTECTED]:~/build/php-5.2-debug$ bash /tmp/run.sh /tmp/run.sh: line 1: ulimit: pipe size: cannot modify limit: Invalid argument sh: line 0: echo: write error: Bad file descriptor test ------------------------------------------------------------------------ [2006-05-28 20:30:32] jdolecek at NetBSD dot org 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 this bug report at http://bugs.php.net/?id=37619&edit=1