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'); 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'); 17if (!$php) { 18 die("No php executable defined\n"); 19} 20$cmd = $php . ' -r "\$in = file_get_contents(\'php://stdin\'); fwrite(STDOUT, \$in); fwrite(STDERR, \$in);"'; 21$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w')); 22$stdin = str_repeat('*', 2049 ); 23 24$options = array_merge(array('suppress_errors' => true, 'bypass_shell' => false)); 25$process = proc_open($cmd, $descriptors, $pipes, getcwd(), array(), $options); 26 27foreach ($pipes as $pipe) { 28 stream_set_blocking($pipe, false); 29} 30$writePipes = array($pipes[0]); 31$stdinLen = strlen($stdin); 32$stdinOffset = 0; 33 34unset($pipes[0]); 35 36$procOutput = []; 37while ($pipes || $writePipes) { 38 $r = $pipes; 39 $w = $writePipes; 40 $e = null; 41 $n = stream_select($r, $w, $e, 60); 42 43 if (false === $n) { 44 break; 45 } elseif ($n === 0) { 46 proc_terminate($process); 47 48 } 49 if ($w) { 50 $written = fwrite($writePipes[0], substr($stdin, $stdinOffset), 8192); 51 if (false !== $written) { 52 $stdinOffset += $written; 53 } else { 54 die('Failed to write to pipe'); 55 } 56 if ($stdinOffset >= $stdinLen) { 57 fclose($writePipes[0]); 58 $writePipes = null; 59 } 60 } 61 62 foreach ($r as $pipe) { 63 $type = array_search($pipe, $pipes); 64 $data = fread($pipe, 8192); 65 if (feof($pipe)) { 66 fclose($pipe); 67 unset($pipes[$type]); 68 } elseif (false === $data) { 69 die('Failed to read from pipe'); 70 } else { 71 $procOutput[$type] = ($procOutput[$type] ?? '') . $data; 72 } 73 } 74} 75foreach ($procOutput as $output) { 76 if ($output !== $stdin) { 77 die('Output does not match input: ' . $output); 78 } 79} 80echo "OK."; 81?> 82--EXPECT-- 83OK. 84