1--TEST-- 2Bug #60120 (proc_open hangs when data in stdin/out/err is getting larger or equal to 2048) 3--SKIPIF-- 4<?php 5$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); 6if (!$php) { 7 die("skip No php executable defined\n"); 8} 9if (PHP_OS_FAMILY === 'Windows') die('skip not for Windows'); 10?> 11--FILE-- 12<?php 13 14error_reporting(E_ALL); 15 16$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED'); 17$cmd = $php . ' -r "\$in = file_get_contents(\'php://stdin\'); fwrite(STDOUT, \$in); fwrite(STDERR, \$in);"'; 18$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w')); 19$stdin = str_repeat('*', 2049 ); 20 21$options = array_merge(array('suppress_errors' => true, 'bypass_shell' => false)); 22$process = proc_open($cmd, $descriptors, $pipes, getcwd(), array(), $options); 23 24foreach ($pipes as $pipe) { 25 stream_set_blocking($pipe, false); 26} 27$writePipes = array($pipes[0]); 28$stdinLen = strlen($stdin); 29$stdinOffset = 0; 30 31unset($pipes[0]); 32 33$procOutput = []; 34while ($pipes || $writePipes) { 35 $r = $pipes; 36 $w = $writePipes; 37 $e = null; 38 $n = stream_select($r, $w, $e, 60); 39 40 if (false === $n) { 41 break; 42 } elseif ($n === 0) { 43 proc_terminate($process); 44 45 } 46 if ($w) { 47 $written = fwrite($writePipes[0], substr($stdin, $stdinOffset), 8192); 48 if (false !== $written) { 49 $stdinOffset += $written; 50 } else { 51 die('Failed to write to pipe'); 52 } 53 if ($stdinOffset >= $stdinLen) { 54 fclose($writePipes[0]); 55 $writePipes = null; 56 } 57 } 58 59 foreach ($r as $pipe) { 60 $type = array_search($pipe, $pipes); 61 $data = fread($pipe, 8192); 62 if (feof($pipe)) { 63 fclose($pipe); 64 unset($pipes[$type]); 65 } elseif (false === $data) { 66 die('Failed to read from pipe'); 67 } else { 68 $procOutput[$type] = ($procOutput[$type] ?? '') . $data; 69 } 70 } 71} 72foreach ($procOutput as $output) { 73 if ($output !== $stdin) { 74 die('Output does not match input: ' . $output); 75 } 76} 77echo "OK."; 78?> 79--EXPECT-- 80OK. 81