为什么从管道中读取16kb + 1个字节会挂起?

时间:2012-11-29 14:58:45

标签: ruby unix jruby pipe

我有一个简单的测试用例,用于读取通过MRI的管道并在JRuby 1.7+中失败。它被报告为JRUBY-6986中的一个关键错误。

tl; dr 为什么从管道读取16kb(16384字节)文件并且16kb + 1字节文件失败?在另一个系统上,发现阈值为72kb(73728字节)。

$ ruby testpipe.rb 16384
Starting...didn't hang!
$ ruby testpipe.rb 16385
Starting...^C

在那里,脚本以16kb + 1字节挂起。

require 'open3'
path = "test.txt"
File.open(path, 'w') { |f| f.write('Z' * ARGV[0].to_i) }
STDOUT.write "Starting..."
Open3.popen3('cat', path) do |stdin, stdout, stderr|
  stdin.close
  readers = [stdout, stderr]
  while readers.any?
    ready = IO.select(readers, [], readers)
    # no writers
    # ready[1].each { ... }
    ready[0].each do |fd|
      if fd.eof?
        fd.close
        readers.delete fd
      else
        # read from pipe one byte at a time
        fd.readpartial 1
      end
    end
  end
end
puts "didn't hang!"

某些操作系统或JVM缓冲区大小是否会导致将不同的信号发送到IO.select或其他什么内容?

PS。我与Jesse Storimer的作者Working With UNIX processes进行了双倍检查,他认为我对IO.select等的使用是正确的。

0 个答案:

没有答案