71 lines
2.4 KiB
Ruby
71 lines
2.4 KiB
Ruby
require "vagrant/util/platform"
|
|
|
|
module Vagrant
|
|
module Util
|
|
class IO
|
|
# The chunk size for reading from subprocess IO.
|
|
READ_CHUNK_SIZE = 4096
|
|
|
|
# Reads data from an IO object while it can, returning the data it reads.
|
|
# When it encounters a case when it can't read anymore, it returns the
|
|
# data.
|
|
#
|
|
# @return [String]
|
|
def self.read_until_block(io)
|
|
data = ""
|
|
|
|
while true
|
|
begin
|
|
if Platform.windows?
|
|
# Windows doesn't support non-blocking reads on
|
|
# file descriptors or pipes so we have to get
|
|
# a bit more creative.
|
|
|
|
# Check if data is actually ready on this IO device.
|
|
# We have to do this since `readpartial` will actually block
|
|
# until data is available, which can cause blocking forever
|
|
# in some cases.
|
|
results = ::IO.select([io], nil, nil, 0.1)
|
|
break if !results || results[0].empty?
|
|
|
|
# Read!
|
|
data << io.readpartial(READ_CHUNK_SIZE).encode("UTF-8", Encoding.default_external)
|
|
else
|
|
# Do a simple non-blocking read on the IO object
|
|
data << io.read_nonblock(READ_CHUNK_SIZE)
|
|
end
|
|
rescue Exception => e
|
|
# The catch-all rescue here is to support multiple Ruby versions,
|
|
# since we use some Ruby 1.9 specific exceptions.
|
|
|
|
breakable = false
|
|
if e.is_a?(EOFError)
|
|
# An `EOFError` means this IO object is done!
|
|
breakable = true
|
|
elsif defined?(::IO::WaitReadable) && e.is_a?(::IO::WaitReadable)
|
|
# IO::WaitReadable is only available on Ruby 1.9+
|
|
|
|
# An IO::WaitReadable means there may be more IO but this
|
|
# IO object is not ready to be read from yet. No problem,
|
|
# we read as much as we can, so we break.
|
|
breakable = true
|
|
elsif e.is_a?(Errno::EAGAIN)
|
|
# Otherwise, we just look for the EAGAIN error which should be
|
|
# all that IO::WaitReadable does in Ruby 1.9.
|
|
breakable = true
|
|
end
|
|
|
|
# Break out if we're supposed to. Otherwise re-raise the error
|
|
# because it is a real problem.
|
|
break if breakable
|
|
raise
|
|
end
|
|
end
|
|
|
|
data
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|