当与stream_select一起使用时,总是在通过 PHP 的proc_open打开的管道读取时被阻止


always blocked on reading from pipe opened through php's proc_open when used with stream_select

我正在谈论一个需要用户交互的进程,使用以下方法(PHP 5.3/Ubuntu 12.04),

$pdes = array(
  0 => array('pipe', 'r'), //child's stdin
  1 => array('pipe', 'w'), //child's stdout
);
$process = proc_open($cmd, $pdes, $pipes);
sleep(1);
if(is_resource($process)){
  while($iter-->0){
    $r=array($pipes[1]);
    $w=array($pipes[0]);
    $e=array();
    if(0<($streams=stream_select($r,$w,$e,2))){
      if($streams){
        if($r){
          echo "reading'n";
          $rbuf.=fread($pipes[1],$rlen);  //reading rlen bytes from pipe
        }else{
          echo "writing'n";
          fwrite($pipes[0],$wbuf."'n");  //writing to pipe
          fflush($pipes[0]);
  }}}}
  fclose($pipes[0]);
  fclose($pipes[1]);
  echo "exitcode: ".proc_close($process)."'n";
}

这是我的 C 语言测试程序,

#include <stdio.h>
int main(){
  char buf[512];
  printf("before input'n");
  scanf("%s",buf);
  printf("after input'n");
  return 0;
}

现在,问题是$r stream_select后总是空的,即使$pipes[1]设置为非阻塞,而写入$pipes[0]永远不会阻塞。但是,在没有stream_select的情况下一切正常,即如果我将读取和写入与测试程序匹配,

echo fread($pipes[1],$rlen);   //matching printf before input
fwrite($pipes[0],$wbuf."'n");  //matching scanf
fflush($pipes[0]);
echo fread($pipes[1],$rlen);   //matching printf after input

我不知道这里发生了什么。我正在尝试在这里实现某种基于 Web 的终端模拟器。欢迎就如何做到这一点提出任何建议:)

对不起,伙计们浪费了你的时间。过了一会儿我就想出了问题(抱歉更新晚了)。由于争用条件,读取被阻止。

我写信给流程并立即检查流的可用性。写入永远不会阻塞,数据还没有准备好读取(不知何故,即使是 1 字节的数据可用,也需要 600 毫秒)。因此,我能够通过在写入块末尾添加 sleep(1) 来解决问题。