Bug #69049 [Fbk]: Unable to get output of slow process
| From: | ab@php.net | Date: | Fri, 13 Feb 2015 11:40:20 +0000 |
| Subject: | Bug #69049 [Fbk]: Unable to get output of slow process | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-190658@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=69049&edit=1
ID: 69049
Updated by: ab@php.net
Reported by: aserbulov at parallels dot com
Summary: Unable to get output of slow process
Status: Feedback
Type: Bug
Package: Streams related
Operating System: Windows
PHP Version: 5.5.21
Block user comment: N
Private report: N
New Comment:
@aserbulov, there are multiple issues with proc_open
- blocking read as file descriptors on windows don't support async, it's not possible to
select()
- internal streams buffering, say you write 1024 but process.php outs only 4 bytes
- pipe buffer size which is way to small on windows, that leads to deadlocks
At the end line - it is much more likely to get a proc_open() call hanging before that patch. Not
mentioning the cases where process.php (or any counterpart) dies leaking the descriptors - then
we've no chance to check it at all. Now we discovered that there is this side effect, however
please keep in mind that this topic is way too complicated. For now, maybe it'd make sense to
increase the internal retry time to something like 60 seconds.
Cheers.
Previous Comments:
------------------------------------------------------------------------
[2015-02-13 11:27:57] ab@php.net
I mean doing it like this
process.php
<?php
sleep(30); // Do some work
fwrite(STDERR, "alive");
sleep(30); // Do some work
fwrite(STDOUT, 'done');
exit(0);
?>
test.php
<?php
$cmd = "\"" . PHP_BINARY . "\" " . dirname(__FILE__) .
"/process.php";
$status;
$stdout = "";
$stderr = "";
$pipes = [];
$descriptors = [
0 => ["pipe", "r"], // stdin
1 => ["pipe", "w"], // stdout
2 => ["pipe", "w"], // stderr
];
$process = proc_open($cmd, $descriptors, $pipes);
fclose($pipes[0]);
while (!feof($pipes[1]) || !feof($pipes[2])) {
$stdout .= fread($pipes[1], 1024);
$stderr .= fread($pipes[2], 1024); /* throw away */
}
fclose($pipes[1]);
fclose($pipes[2]);
$status = proc_close($process);
print_r(["status" => $status, "stdout" => $stdout]);
------------------------------------------------------------------------
[2015-02-13 10:53:00] aserbulov at parallels dot com
In any case, you should not break working code during bug https://bugs.php.net/bug.php?id=51800 fixing.
------------------------------------------------------------------------
[2015-02-13 10:39:06] aserbulov at parallels dot com
while (!feof($pipes[1]) || !feof($pipes[2])) {
$stdout .= fread($pipes[1], 1024); // wait ~32 seconds, set eof and return empty string
$stderr .= fread($pipes[2], 1024); // wait ~28 seconds, set eof and return empty string
}
------------------------------------------------------------------------
[2015-02-13 10:34:06] aserbulov at parallels dot com
I understand, why it was done and think what you should implement another solution for bug https://bugs.php.net/bug.php?id=51800.
With the particular issue, I can't implement it with a slow process.
---
$process = proc_open($cmd, $descriptors, $pipes);
fclose($pipes[0]);
while (!feof($pipes[1]) || !feof($pipes[2])) {
$stdout .= fread($pipes[1], 1024); // wait ~32 seconds, set eof and return empty string
$stderr .= fread($pipes[2], 1024); // set eof and return empty string
}
fclose($pipes[1]);
fclose($pipes[2]);
status = proc_close($process);
---
------------------------------------------------------------------------
[2015-02-13 09:06:14] ab@php.net
Hi,
thanks for the report. Just removing that part doesn't seem to be a correct solution. Please
reread the tickets you've linked for why it was done so.
With the particular issue, you can still implement it with a slow process. I'd suggest to not
to close strerr but read from it simultaneously. You expect a keyword 'done' from the
stdout, but that doesn't prevent you to read some kind of keep-alive stuff from stderr. You
might also look up some example in the tests appended with the bug #51800.
Of course it's bad when not having control over process.php . I was thinking about introducing
a userspace function to peek on the pipe content. Another possibility were to introduce one more
option to proc_open which would set the expected timeout. But none of that is yet done, lets see
whether it's needed at all.
Thanks.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=69049
--
Edit this bug report at https://bugs.php.net/bug.php?id=69049&edit=1