Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-blocking on STDIN in PHP CLI

Tags:

php

stdin

Is there anyway to read from STDIN with PHP that is non blocking:

I tried this:

stream_set_blocking(STDIN, false);
echo fread(STDIN, 1);

and this:

$stdin = fopen('php://stdin', 'r');
stream_set_blocking($stdin, false);
echo 'Press enter to force run command...' . PHP_EOL;
echo fread($stdin, 1);

but it still blocks until fread gets some data.

I noticed a few open bug reports about this (7 years old), so if it can't be done, does any one know any crude hacks that could accomplish this (on Windows and Linux)?

  • https://bugs.php.net/bug.php?id=34972
  • https://bugs.php.net/bug.php?id=47893
  • https://bugs.php.net/bug.php?id=48684
like image 763
Petah Avatar asked Feb 20 '12 04:02

Petah


1 Answers

Here's what I could come up with. It works fine in Linux, but on Windows, as soon as I hit a key, the input is buffered until enter is pressed. I don't know a way to disable buffering on a stream.

<?php

function non_block_read($fd, &$data) {
    $read = array($fd);
    $write = array();
    $except = array();
    $result = stream_select($read, $write, $except, 0);
    if($result === false) throw new Exception('stream_select failed');
    if($result === 0) return false;
    $data = stream_get_line($fd, 1);
    return true;
}

while(1) {
    $x = "";
    if(non_block_read(STDIN, $x)) {
        echo "Input: " . $x . "\n";
        // handle your input here
    } else {
        echo ".";
        // perform your processing here
    }
}

?>
like image 186
Martin Avatar answered Sep 23 '22 05:09

Martin