From: Amos Date: 2002-01-29T16:11:08+09:00 Subject: Re: Open3 (more on thread) >>>>> On Tue, 29 Jan 2002 10:38:14 +0900, >>>>> nobu nokada (nn) writes: nn> Like this? nn> th = Thread.current nn> Thread.new { nn> Process.waitpid(pid) nn> $? == 0 or th.raise(ChildDied.new($?, cmd)) nn> } Why the use of Thread? I wrote a script that used this open3 to run another script that ended with 'exit 1'. I then ran this mess like this: while :; do ./runcmd.rb ; done Well, sometimes the exception was raised, and sometimes it wasn't. So I fiddled with it some and came up with this. It also passes the pipes back so that they can be accessed in the rescue clause. module Open3 class ChildDied < StandardError def initialize(code, cmd, pipes) @code = code @cmd = cmd @pipes = pipes end attr_reader :code, :cmd, :pipes 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 pi = [pw[1], pr[0], pe[0]] Process.waitpid(pid) $? == 0 or raise(ChildDied.new($?, cmd, pi)) defined?(yield) or return pi begin yield(*pi) ensure pi.each{|p| p.close unless p.closed?} end end module_function :popen3 end