fgetsがfgetsに見えなくなる時@PHP

外部プロセスをpopenで起動してfgetsする際、1行単位で文字列取得しなくなるコード例。単なるメモ。

PHPプロセス側をノンブロッキング設定する*1のに加えて、外部プロセス側の標準出力行バッファリングが無効になってないといけない*2

PHPコード(code.php)、

<?php
$res = popen("./a.out", "r");
stream_set_blocking($res, 0);
for(;;){
  $str = fgets($res);
  var_dump($str);
  sleep(1);
 }
?>

外部コード(code.c)、

#include <unistd.h>
#include <stdio.h>

int main(){
  int cnt = 0;
  setvbuf(stdout, 0, _IONBF, 0);
  for(;;){
    if(++cnt == 5){
      cnt = 0;
      printf("b\n");
    }else{
      printf("a");
    }
    sleep(2);
  }
}

実行例:

$ gcc code.c
$ php code.php
string(1) "a"
bool(false)
string(1) "a"
bool(false)
string(1) "a"
bool(false)
string(1) "a"
bool(false)
string(2) "b
"
bool(false)