Hi,

At Tue, 29 Jan 2002 09:54:33 +0900,
Amos <amos+lists.ruby-talk / utdallas.edu> wrote:
> I was searching through the ruby-talk.org archive (very helpful!) on
> Open3.  One issue that I guess is still unresolved (?) is not
> getting the exit status back.  Would not a more OO way be to throw
> an exception for a non-zero exit status?

Like this?

module Open3
  class ChildDied < StandardError
    def initialize(code, cmd)
      @code = code
      @cmd = cmd
    end
    attr_reader :code, :cmd
  end

  def popen3(*cmd)
    pw = IO::pipe
    pr = IO::pipe
    pe = IO::pipe
    pid = fork {
      pw[1].close; STDIN.reopen(pw[0]); pw[0].close
      pr[0].close; STDOUT.reopen(pr[1]); pr[1].close
      pe[0].close; STDERR.reopen(pe[1]); pe[1].close
      exec(*cmd)
    }
    pw[0].close
    pr[1].close
    pe[1].close
    th = Thread.current
    Thread.new {
      Process.waitpid(pid)
      $? == 0 or th.raise(ChildDied.new($?, cmd))
    }
    pi = [pw[1], pr[0], pe[0]]
    defined?(yield) or return pi
    begin
      yield(*pi)
    ensure
      pi.each{|p| p.close unless p.closed?}
    end
  end
  module_function :popen3
end

-- 
Nobu Nakada