summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Joye <pajoye@php.net>2011-10-24 12:39:55 +0000
committerPierre Joye <pajoye@php.net>2011-10-24 12:39:55 +0000
commit97076fa68e71c6afda4706a4f1f6d2a87ded6e26 (patch)
treef1bcc00265e7f70f8eaaa08c0dc89ef0f4871e42
parent4321da0388bf55bfa4be8d8c865ef771b08ba953 (diff)
downloadphp-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--NEWS4
-rw-r--r--ext/standard/proc_open.c2
-rw-r--r--ext/standard/tests/file/bug60120.phpt74
3 files changed, 79 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index ab974183fc..83d1566909 100644
--- a/NEWS
+++ b/NEWS
@@ -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.