pajoye                                   Mon, 24 Oct 2011 12:39:55 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=318366

Log:
- fixed bug #60120, proc_open's streams may hang with stdin/out/err when the 
data exceeds or is equal to 2048 bytes

Bug: https://bugs.php.net/60120 (Assigned) proc_open hangs with stdin/out with 
2048+ bytes
      
Changed paths:
    U   php/php-src/branches/PHP_5_3/NEWS
    U   php/php-src/branches/PHP_5_3/ext/standard/proc_open.c
    A   php/php-src/branches/PHP_5_3/ext/standard/tests/file/bug60120.phpt
    U   php/php-src/branches/PHP_5_4/NEWS
    U   php/php-src/branches/PHP_5_4/ext/standard/proc_open.c
    A   php/php-src/branches/PHP_5_4/ext/standard/tests/file/bug60120.phpt
    U   php/php-src/trunk/ext/standard/proc_open.c
    A   php/php-src/trunk/ext/standard/tests/file/bug60120.phpt

Modified: php/php-src/branches/PHP_5_3/NEWS
===================================================================
--- php/php-src/branches/PHP_5_3/NEWS	2011-10-24 12:34:44 UTC (rev 318365)
+++ php/php-src/branches/PHP_5_3/NEWS	2011-10-24 12:39:55 UTC (rev 318366)
@@ -3,6 +3,8 @@
 ?? ??? 2011, PHP 5.3.9

 - 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)
   . Fixed bug #60019 (Function time_nanosleep() is undefined on OS X). (Ilia)
   . Fixed bug #55798 (serialize followed by unserialize with numeric object
     prop. gives integer prop). (Gustavo)

Modified: php/php-src/branches/PHP_5_3/ext/standard/proc_open.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/standard/proc_open.c	2011-10-24 12:34:44 UTC (rev 318365)
+++ php/php-src/branches/PHP_5_3/ext/standard/proc_open.c	2011-10-24 12:39:55 UTC (rev 318366)
@@ -451,7 +451,7 @@

 /* {{{ 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"


Added: php/php-src/branches/PHP_5_3/ext/standard/tests/file/bug60120.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/standard/tests/file/bug60120.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/standard/tests/file/bug60120.phpt	2011-10-24 12:39:55 UTC (rev 318366)
@@ -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.

Modified: php/php-src/branches/PHP_5_4/NEWS
===================================================================
--- php/php-src/branches/PHP_5_4/NEWS	2011-10-24 12:34:44 UTC (rev 318365)
+++ php/php-src/branches/PHP_5_4/NEWS	2011-10-24 12:39:55 UTC (rev 318366)
@@ -9,6 +9,10 @@
     (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)

Modified: php/php-src/branches/PHP_5_4/ext/standard/proc_open.c
===================================================================
--- php/php-src/branches/PHP_5_4/ext/standard/proc_open.c	2011-10-24 12:34:44 UTC (rev 318365)
+++ php/php-src/branches/PHP_5_4/ext/standard/proc_open.c	2011-10-24 12:39:55 UTC (rev 318366)
@@ -377,7 +377,7 @@

 /* {{{ 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"


Added: php/php-src/branches/PHP_5_4/ext/standard/tests/file/bug60120.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/ext/standard/tests/file/bug60120.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_4/ext/standard/tests/file/bug60120.phpt	2011-10-24 12:39:55 UTC (rev 318366)
@@ -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.

Modified: php/php-src/trunk/ext/standard/proc_open.c
===================================================================
--- php/php-src/trunk/ext/standard/proc_open.c	2011-10-24 12:34:44 UTC (rev 318365)
+++ php/php-src/trunk/ext/standard/proc_open.c	2011-10-24 12:39:55 UTC (rev 318366)
@@ -377,7 +377,7 @@

 /* {{{ 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"


Added: php/php-src/trunk/ext/standard/tests/file/bug60120.phpt
===================================================================
--- php/php-src/trunk/ext/standard/tests/file/bug60120.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/standard/tests/file/bug60120.phpt	2011-10-24 12:39:55 UTC (rev 318366)
@@ -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.
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to