How to check whether stream has any data?
Asked Answered
F

2

6

This what I'm trying to do:

$output = '';
$stream = popen("some-long-running-command 2>&1", 'r');
while (!feof($stream)) {
  $meta = stream_get_meta_data($stream);
  if ($meta['unread_bytes'] > 0) {
    $line = fgets($stream);
    $output .= $line;
  }
  echo ".";
}
$code = pclose($stream);

Looks like this code is not correct, since it gets stuck at the call to stream_get_meta_data(). What is the right way to check whether the stream has some data to read? The whole point here is to avoid locking at fgets().

Fuddyduddy answered 19/12, 2012 at 13:59 Comment(1)
fgets() locks because it waits for a "new-line" character. Use stream_get_contents() with the length argument instead: $line = stream_get_contents($stream, $meta['unread_bytes']);Necrotomy
D
7

The correct way to do this is with stream_select():

$stream = popen("some-long-running-command 2>&1", 'r');
while (!feof($stream)) {
  $r = array($stream);
  $w = $e = NULL;

  if (stream_select($r, $w, $e, 1)) {
    // there is data to be read
  }
}
$code = pclose($stream);

One thing to note though (I'm not sure about this) is that it may be the feof() check that is "blocking" - it may be that the loop never ends because the child process does not close its STDOUT descriptor.

Douville answered 19/12, 2012 at 14:3 Comment(1)
It is important to note that, as @Douville has done, if you are going to use NULL you MUST assign it to a variable in order to avoid trouble with passing a non-variable by reference (which is how the first three parameters are declared). Read the notes at php.net/manual/en/function.stream-select.phpEighteenmo
S
0

If you want to test whether or not your cli command has something in STDIN without reading it, you can also use stream_select.

$r = [STDIN];
$w = $e = NULL;
$hasStdin = stream_select($r, $w, $e, 0);
if ($hasStdin) {
  //do something
}
Steeplejack answered 16/7 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.