]> granicus.if.org Git - php/commitdiff
- fixed bug #60120, proc_open's streams may hang with stdin/out/err when the data...
authorPierre Joye <pajoye@php.net>
Mon, 24 Oct 2011 12:39:55 +0000 (12:39 +0000)
committerPierre Joye <pajoye@php.net>
Mon, 24 Oct 2011 12:39:55 +0000 (12:39 +0000)
NEWS
ext/standard/proc_open.c
ext/standard/tests/file/bug60120.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index ab974183fcdb5c4c5486b919ee62f7fb3c689c4f..83d15669098c9ab17fcd8054754dd8823b17b67d 100644 (file)
--- 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) 
index c8ce705251477c9a2084fe74cd5d9c5fc879aab4..1caa56945d40ee86eeeaa0517353779f490443cd 100644 (file)
@@ -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 (file)
index 0000000..8915bb8
--- /dev/null
@@ -0,0 +1,74 @@
+--TEST--\r
+Bug #60120 (proc_open hangs when data in stdin/out/err is getting larger or equal to 2048)\r
+--SKIPIF--\r
+<?php\r
+if (substr(PHP_OS, 0, 3) != 'WIN') {\r
+    die('skip only for Windows');\r
+}\r
+$php = getenv('TEST_PHP_EXECUTABLE');\r
+if (!$php) {\r
+       die("No php executable defined\n");\r
+}\r
+?>\r
+--FILE--\r
+<?php\r
+\r
+error_reporting(E_ALL);\r
+\r
+$php = getenv('TEST_PHP_EXECUTABLE');\r
+if (!$php) {\r
+       die("No php executable defined\n");\r
+}\r
+$cmd = 'php -r "fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);"';\r
+$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));\r
+$stdin = str_repeat('*', 1024 * 16) . '!';\r
+$stdin = str_repeat('*', 2049 );\r
+\r
+$options = array_merge(array('suppress_errors' => true, 'binary_pipes' => true, 'bypass_shell' => false));\r
+$process = proc_open($cmd, $descriptors, $pipes, getcwd(), array(), $options);\r
+\r
+foreach ($pipes as $pipe) {\r
+    stream_set_blocking($pipe, false);\r
+}\r
+$writePipes = array($pipes[0]);\r
+$stdinLen = strlen($stdin);\r
+$stdinOffset = 0;\r
+\r
+unset($pipes[0]);\r
+\r
+while ($pipes || $writePipes) {\r
+    $r = $pipes;\r
+    $w = $writePipes;\r
+    $e = null;\r
+    $n = stream_select($r, $w, $e, 60);\r
+\r
+    if (false === $n) {\r
+        break;\r
+    } elseif ($n === 0) {\r
+        proc_terminate($process);\r
+\r
+    }\r
+    if ($w) {\r
+        $written = fwrite($writePipes[0], (binary)substr($stdin, $stdinOffset), 8192);\r
+        if (false !== $written) {\r
+            $stdinOffset += $written;\r
+        }\r
+        if ($stdinOffset >= $stdinLen) {\r
+            fclose($writePipes[0]);\r
+            $writePipes = null;\r
+        }\r
+    }\r
+\r
+    foreach ($r as $pipe) {\r
+        $type = array_search($pipe, $pipes);\r
+        $data = fread($pipe, 8192);\r
+        if (false === $data || feof($pipe)) {\r
+            fclose($pipe);\r
+            unset($pipes[$type]);\r
+        }\r
+    }\r
+}\r
+echo "OK.";\r
+?>\r
+--EXPECT--\r
+OK.\r