ruby – STDIN的非阻塞readline?

在正确设置为非阻塞模式时,我无法弄清楚为什么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成功设置了非阻塞模式,但所有IO函数(如read,readline,gets,readchar)都忽略该模式,并在未收到任何输入时挂起.

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

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

我知道IO.read_nonblock,但寻找一种有效的方法来读取换行终止字符串.为每个单个字符调用read_nonblock非常慢.

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

最佳答案 这有点不幸但IO模块的标准函数似乎不尊重与文件描述符相关的状态标志.

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

在预先知道字符/字节数量的情况下,库存IO.read_nonblock将很好地服务.

点赞