|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2010-05-12 17:31 UTC] ph dot wolfer at googlemail dot com
Description:
------------
On Windows, if you use proc_open to open another process and if you use a pipe for STDERR, the script will hang when trying to read from STDOUT or STDERR if the opened process outputs a lot of data.
See the example below. The called script process.php is a simple script which writes some data to STDOUT and STDERR:
$data = str_repeat("a", 10000);
fwrite(STDOUT, $data);
fwrite(STDERR, $data);
exit(0);
If called as shown below, the script will hang in the loop that reads the STDOUT pipe. The same would happen if you would read the STDERR pipe before. If you lower the amount of data in process.php the script will run to the end. In my tests everything below ~2000 bytes was ok, above this value the script hang.
If you change the script below to not include the STDERR descriptor or if you change the STDERR descriptor to a file output everything will work fine. Also if you close the STDERR pipe before reading from STDOUT it will work. There seems to be some deadlock.
The same script works fine on Linux.
This was tested with Windows Server 2008, IIS, PHP 5.2.13. But I have seen this on other Windows configurations as well.
Test script:
---------------
<?php
$cmd = "\"C:/Program Files/php/php.exe\" process.php";
$status;
$stdout = "";
$stderr = "";
$pipes = array();
$descriptors = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
);
$process = proc_open($cmd, $descriptors, $pipes);
if (is_resource($process))
{
fclose($pipes[0]);
while (!feof($pipes[1]))
$stdout .= fread($pipes[1], 1024);
fclose($pipes[1]);
while (!feof($pipes[2]))
$stderr .= fread($pipes[2], 1024);
fclose($pipes[2]);
$status = proc_close($process);
}
print_r(array(
"status" => $status,
"stdout" => $stdout,
"stderr" => $stderr,
));
?>
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 16:00:01 2025 UTC |
I could reproduce this on PHP 5.4.0 as soon as $data is longer than 4096 bytes. With $data = str_repeat("a", 4097); in process.php it hangs forever, while with any number until 4096 it passes.it seems that the issue is on main/streams.c:679 if (stream->writepos - stream->readpos < (off_t)size) { where writepos and readpos are equals. Anatolyi, please take a look at it.Could you please try this slightly modified php snippet? ============ START process.php =============== <?php $how_much = 10000; $data0 = str_repeat("a", $how_much); $data1 = str_repeat("b", $how_much); fwrite(STDOUT, $data0); fwrite(STDERR, $data1); exit(0); ============ END process.php =============== ============ START 51800.php =============== <?php $cmd = "\"C:/php-sdk/php55/vc11/x86/php-src/Debug/php.exe\" process.php"; $status; $stdout = ""; $stderr = ""; $pipes = array(); $descriptors = array( 0 => array("pipe", "rb"), // stdin 1 => array("pipe", "wb"), // stdout 2 => array("pipe", "wb") // stderr ); $process = proc_open($cmd, $descriptors, $pipes); if (is_resource($process)) { fclose($pipes[0]); while (!feof($pipes[1]) || !feof($pipes[2])) { $stdout .= fread($pipes[1], 1024); $stderr .= fread($pipes[2], 1024); } fclose($pipes[1]); fclose($pipes[2]); $status = proc_close($process); } print_r(array( "status" => $status, "stdout" => $stdout, "stderr" => $stderr, )); ============ END 51800.php =============== This bug might be pretty much not a php bug, but the consequence of the pipe nature.