STDIN的非阻塞读取线?

时间:2014-09-08 14:15:25

标签: ruby unix stdin pipe

我无法弄清楚为什么IO方法在正确设置为非阻塞模式时不会对STDIN起作用:

  require 'fcntl'

  stdin_flags = STDIN.fcntl(Fcntl::F_GETFL)
  p stdin_flags   #32770
  p STDIN.fcntl(Fcntl::F_SETFL, stdin_flags | Fcntl::O_NONBLOCK) # 0
  p STDIN.fcntl(Fcntl::F_GETFL)    # 34818
  #at_exit { STDIN.fcntl(Fcntl::F_SETFL, stdin_flags & ~Fcntl::O_NONBLOCK) }
  STDIN.readline    # this call blocks, IO::EAGAINWaitReadable expected
  exit

IO.fcntl成功设置了非阻止模式,但readreadlinegetsreadchar等所有IO功能都会忽略该模式并在读取时挂起没有收到任何意见。

将同步模式设置为true无效。

如果我用shell调用STDIN.readline替换system('read line'),它确实可以正常工作。如果设置了非阻塞模式,它将不会等待或等待输入。

我了解IO.read_nonblock,但正在寻找一种有效的方法来阅读换行终止字符串。为每个单个字符调用read_nonblock非常缓慢。

有人可以解释这个(错误的)行为吗?

1 个答案:

答案 0 :(得分:2)

这有点不幸,但IO模块的标准函数似乎不尊重与文件描述符关联的状态标志。

其中一个工作解决方案是使用IO.select类方法进行输入轮询,然后在常规方法可用时读取数据。 请注意,在使用行处理方法时,代码可能会挂起,直到终止换行符被消耗为止。当事情失控时,建议在Timeout块中包含轮询代码。

如果预先知道字符数/字节数,则库存IO.read_nonblock只会很好用。