我无法弄清楚为什么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
成功设置了非阻止模式,但read
,readline
,gets
,readchar
等所有IO功能都会忽略该模式并在读取时挂起没有收到任何意见。
将同步模式设置为true无效。
如果我用shell调用STDIN.readline
替换system('read line')
,它确实可以正常工作。如果设置了非阻塞模式,它将不会等待或等待输入。
我了解IO.read_nonblock
,但正在寻找一种有效的方法来阅读换行终止字符串。为每个单个字符调用read_nonblock
非常缓慢。
有人可以解释这个(错误的)行为吗?
答案 0 :(得分:2)
这有点不幸,但IO
模块的标准函数似乎不尊重与文件描述符关联的状态标志。
其中一个工作解决方案是使用IO.select
类方法进行输入轮询,然后在常规方法可用时读取数据。
请注意,在使用行处理方法时,代码可能会挂起,直到终止换行符被消耗为止。当事情失控时,建议在Timeout
块中包含轮询代码。
如果预先知道字符数/字节数,则库存IO.read_nonblock
只会很好用。