module SpawnProcess class NonSuccessStatus < StandardError attr_accessor :status def initialize(str, status) @status = status super(str) end end def self.do(*args, &block) args = args.map(&:to_s) in_r, in_w = IO.pipe() out_r, out_w = IO.pipe() err_r, err_w = IO.pipe() pid = spawn(*args, :in => in_r, :out => out_w, :err => err_w) in_r.close out_w.close err_w.close if block in_w.write(block.call()) end in_w.close out_reader = Thread.new { out_r.read } err_reader = Thread.new { err_r.read } Process.waitpid(pid) out_str = out_reader.value err_str = err_reader.value out_r.close err_r.close if !$?.success? raise NonSuccessStatus.new(err_str, $?) end out_str end end