class Terrapin::CommandLine::MultiPipe
def close_read
def close_read begin @stdout_in.close rescue IOError # do nothing end begin @stderr_in.close rescue IOError # do nothing end end
def close_write
def close_write @stdout_out.close @stderr_out.close end
def initialize
def initialize @stdout_in, @stdout_out = IO.pipe @stderr_in, @stderr_out = IO.pipe end
def output
def output Output.new(@stdout_output, @stderr_output) end
def pipe_options
def pipe_options { out: @stdout_out, err: @stderr_out } end
def read
def read read_streams(@stdout_in, @stderr_in) end
def read_and_then(&block)
def read_and_then(&block) close_write read block.call close_read end
def read_stream(io)
def read_stream(io) result = String.new begin while partial_result = io.read_nonblock(8192) result << partial_result end rescue EOFError, Errno::EPIPE io.close rescue Errno::EINTR, Errno::EWOULDBLOCK, Errno::EAGAIN # do nothing end result end
def read_streams(output, error)
def read_streams(output, error) @stdout_output = "" @stderr_output = "" read_fds = [output, error] while !read_fds.empty? to_read, = IO.select(read_fds) if to_read.include?(output) @stdout_output << read_stream(output) read_fds.delete(output) if output.closed? end if to_read.include?(error) @stderr_output << read_stream(error) read_fds.delete(error) if error.closed? end end end