Bug #69900 [Opn->Fbk]: Commandline input/output weird behaviour
| From: | ab@php.net | Date: | Thu, 25 Jun 2015 13:15:47 +0000 |
| Subject: | Bug #69900 [Opn->Fbk]: Commandline input/output weird behaviour | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-193880@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=69900&edit=1
ID: 69900
Updated by: ab@php.net
Reported by: nerdbeere2k at gmail dot com
Summary: Commandline input/output weird behaviour
-Status: Open
+Status: Feedback
Type: Bug
Package: *General Issues
Operating System: Linux, Windows
PHP Version: 5.5.26
Block user comment: N
Private report: N
New Comment:
Thanks for the second code snippet. However it turns the ticket to completely different story. When
I run it, i reproduce your findings on Windows, but not on Linux.
It might be related on Windows to bugfixes to the proc_open as it previously could block while
reading/writing pipes from the child. You initially say it's reproducable on both Linux/Windows
and the initial snippet doesn't involve proc_open().
So I'm just not sure what we're investigating on :) Is the last one the code reproducing
your exact situation? If not, it's probably worth to workout a snippet not involving
proc_open().
Thanks.
Previous Comments:
------------------------------------------------------------------------
[2015-06-25 07:31:54] nerdbeere2k at gmail dot com
Status Open
------------------------------------------------------------------------
[2015-06-24 11:22:07] nerdbeere2k at gmail dot com
By the way, if you call the process like this:
$process = proc_open(PHP_BINARY.' <?php while(!feof(STDIN)){ $s = fgets(STDIN);
fwrite(STDOUT, $s); } ?>', $descriptorspec, $pipes);
The problem doesnt occur... just in case someone wonders why i used two separate files.
------------------------------------------------------------------------
[2015-06-24 11:19:08] nerdbeere2k at gmail dot com
Hello ab,
first thank you very much for looking into this! i tried to simplify this more by removing the java
part, and the issue seems to occur here too.
I'd agree with you, its probably not a fgets problem but seems to be a general problem with the
STDIN/STDOUT stream, but i can't point out what it could be as i am not familiar with the php
internals.
However, this is the php-only testcase i came up with where the problem occurs:
<?php
$descriptorspec = array(0 => array("pipe", "r"),1 =>
array("pipe", "w"), 2 => array("file",
"error-output.txt", "a"));
$pipes = array();
$process = proc_open(PHP_BINARY.' -f test.php', $descriptorspec, $pipes);
if(is_resource($process)){
for($i = 0; $i < 10; $i++){
fwrite($pipes[0], "hello\r\n");
$t0 = microtime(1);
$s = fgets($pipes[1]);
$t1 = microtime(1);
echo $s;
echo "fgets() took ", (($t1 - $t0)*1000), "ms\n";
}
fclose($pipes[0]);
fclose($pipes[1]);
proc_close($process);
} else die("process creation failed!");
?>
and the test.php file:
<?php
while(!feof(STDIN)){
$s = fgets(STDIN);
fwrite(STDOUT, $s);
}
?>
The output that php-5.5.26 generates when calling it is as follows:
C:\tmp\php_bug_report_69900\>.\php-5.5.26\php.exe -f passproc.php
hello
fgets() took 100.00491142273ms
hello
fgets() took 100.00610351562ms
hello
fgets() took 100.00610351562ms
hello
fgets() took 100.00586509705ms
hello
fgets() took 100.00514984131ms
hello
fgets() took 100.00586509705ms
hello
fgets() took 100.00610351562ms
hello
fgets() took 100.00491142273ms
hello
fgets() took 100.00610351562ms
hello
fgets() took 100.00586509705ms
The output with php-5.5.17 is as follows:
C:\tmp\php_bug_report_69900\>.\php-5.5.17\php.exe -f passproc.php
hello
fgets() took 19.001007080078ms
hello
fgets() took 0ms
hello
fgets() took 0ms
hello
fgets() took 0ms
hello
fgets() took 0ms
hello
fgets() took 0ms
hello
fgets() took 0ms
hello
fgets() took 0ms
hello
fgets() took 0ms
hello
fgets() took 0ms
Hope this helps! Thanks again!
------------------------------------------------------------------------
[2015-06-24 09:22:06] ab@php.net
Thanks for the report.
I've modified your snippet to see the timings
<?php
while(!feof(STDIN)){
// usleep(1) <- adding this seems to fix this behaviour...
// THIS WILL BLOCK FOR 100ms for every fgets call
$t0 = microtime(1);
$s = fgets(STDIN);
$t1 = microtime(1);
echo "fgets() took ", (($t1 - $t0)*1000), "ms\n";
fwrite(STDOUT, $s);
}
But i don't reproduce this. Call it like
echo hello | php.exe -n bugs\69900.php
on my machine, either PHP 5.5 or 7, the output is like
fgets() took 0.015974044799805ms
hello
fgets() took 0.015974044799805ms
Please provide a stable reproduce case for what you describe. Otherwise, the issue you experience is
probably not fgets().
Thanks.
------------------------------------------------------------------------
[2015-06-22 14:45:22] nerdbeere2k at gmail dot com
Description:
------------
Explaining my whole setup for this would take some time so i'm gonna try to describe it as
short as possible.
I have a java application where i send some string to php-cli via standard input and read a result
string back from standard output to do something else with it.
I do this several times, so the php-cli process is getting several commands to work off, and i read
the results back.
The issue/bug now is that for every fgets call i make the process hangs for 100ms.
This worked like a charm until version php-5.5.17 and broke in version php-5.5.18. php-5.6.* seems
to have this issue as well.
The changelog didn't exactly point towards a change that might've led to this as far as i
could see.
Especially weird is that it all works fine if i put a "usleep(1)" before the fgets call...
I wrote some example breaking down the problem to as few lines as possible:
<?php
while(!feof(STDIN)){
// usleep(1) <- adding this seems to fix this behaviour...
// THIS WILL BLOCK FOR 100ms for every fgets call
$s = fgets(STDIN);
fwrite(STDOUT, $s);
}
?>
This script is called from a java application like this (tested on jdk1.8.0_20):
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec("./php-5.5.18/php.exe -f ./php-5.5.18/test.php");
InputStream inputStream = p.getInputStream();
OutputStream outputStream = p.getOutputStream();
byte[] buffer = new byte[1024];
while(p.isAlive()){
outputStream.write("TEST\r\n".getBytes());
outputStream.flush();
int read = inputStream.read(buffer);
if(read > -1){
System.out.println(new String(buffer, 0, read));
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=69900&edit=1