diff options
| author | Pierre Joye <pajoye@php.net> | 2011-10-24 12:39:55 +0000 |
|---|---|---|
| committer | Pierre Joye <pajoye@php.net> | 2011-10-24 12:39:55 +0000 |
| commit | 97076fa68e71c6afda4706a4f1f6d2a87ded6e26 (patch) | |
| tree | f1bcc00265e7f70f8eaaa08c0dc89ef0f4871e42 | |
| parent | 4321da0388bf55bfa4be8d8c865ef771b08ba953 (diff) | |
| download | php-git-97076fa68e71c6afda4706a4f1f6d2a87ded6e26.tar.gz | |
- fixed bug #60120, proc_open's streams may hang with stdin/out/err when the data exceeds or is equal to 2048 bytes
| -rw-r--r-- | NEWS | 4 | ||||
| -rw-r--r-- | ext/standard/proc_open.c | 2 | ||||
| -rw-r--r-- | ext/standard/tests/file/bug60120.phpt | 74 |
3 files changed, 79 insertions, 1 deletions
@@ -9,6 +9,10 @@ PHP NEWS (Laruence) . Fixed bug #60115 (memory definitely lost in cli server). (Laruence) +- Core: + . Fixed bug #60120 (proc_open's streams may hang with stdin/out/err when + the data exceeds or is equal to 2048 bytes). (Pierre, Pascal Borreli) + 20 Oct 2011, PHP 5.4.0 beta2 - General improvements: . Improve the warning message of incompatible arguments. (Laruence) diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index c8ce705251..1caa56945d 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -377,7 +377,7 @@ PHP_FUNCTION(proc_get_status) /* {{{ handy definitions for portability/readability */ #ifdef PHP_WIN32 -# define pipe(pair) (CreatePipe(&pair[0], &pair[1], &security, 2048L) ? 0 : -1) +# define pipe(pair) (CreatePipe(&pair[0], &pair[1], &security, 0) ? 0 : -1) # define COMSPEC_NT "cmd.exe" diff --git a/ext/standard/tests/file/bug60120.phpt b/ext/standard/tests/file/bug60120.phpt new file mode 100644 index 0000000000..8915bb833c --- /dev/null +++ b/ext/standard/tests/file/bug60120.phpt @@ -0,0 +1,74 @@ +--TEST--
+Bug #60120 (proc_open hangs when data in stdin/out/err is getting larger or equal to 2048)
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die('skip only for Windows');
+}
+$php = getenv('TEST_PHP_EXECUTABLE');
+if (!$php) {
+ die("No php executable defined\n");
+}
+?>
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+$php = getenv('TEST_PHP_EXECUTABLE');
+if (!$php) {
+ die("No php executable defined\n");
+}
+$cmd = 'php -r "fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);"';
+$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
+$stdin = str_repeat('*', 1024 * 16) . '!';
+$stdin = str_repeat('*', 2049 );
+
+$options = array_merge(array('suppress_errors' => true, 'binary_pipes' => true, 'bypass_shell' => false));
+$process = proc_open($cmd, $descriptors, $pipes, getcwd(), array(), $options);
+
+foreach ($pipes as $pipe) {
+ stream_set_blocking($pipe, false);
+}
+$writePipes = array($pipes[0]);
+$stdinLen = strlen($stdin);
+$stdinOffset = 0;
+
+unset($pipes[0]);
+
+while ($pipes || $writePipes) {
+ $r = $pipes;
+ $w = $writePipes;
+ $e = null;
+ $n = stream_select($r, $w, $e, 60);
+
+ if (false === $n) {
+ break;
+ } elseif ($n === 0) {
+ proc_terminate($process);
+
+ }
+ if ($w) {
+ $written = fwrite($writePipes[0], (binary)substr($stdin, $stdinOffset), 8192);
+ if (false !== $written) {
+ $stdinOffset += $written;
+ }
+ if ($stdinOffset >= $stdinLen) {
+ fclose($writePipes[0]);
+ $writePipes = null;
+ }
+ }
+
+ foreach ($r as $pipe) {
+ $type = array_search($pipe, $pipes);
+ $data = fread($pipe, 8192);
+ if (false === $data || feof($pipe)) {
+ fclose($pipe);
+ unset($pipes[$type]);
+ }
+ }
+}
+echo "OK.";
+?>
+--EXPECT--
+OK.
|
