replacement for 'Kernel#system' which captures all output.
This is the *almost* final version.. this may have others interest :-)
Warning: 'stdin' is not yet supported.
Suggestions for improvements is welcome.
def system(command, *args)
#todo: stdin
r1, w1 = IO.pipe # stdout
r2, w2 = IO.pipe # stderr
fdes = [r1, r2]
thread = Thread.new do
loop do
#puts "waiting"
res = select(fdes, nil, nil, nil)[0]
#p res
if res.include?(r1)
#puts "r1"
unless r1.eof
Redir.instance.write_out r1.read
else
#puts "kill r1"
fdes.delete r1
thread.kill if fdes == []
end
end
if res.include?(r2)
#puts "r2"
unless r2.eof
Redir.instance.write_error r2.read
else
#puts "kill r2"
fdes.delete r2
thread.kill if fdes == []
end
end
end
end
pid = Kernel.fork do
r1.close; r2.close
$defout.reopen(w1); $stdout.reopen(w1); $stderr.reopen(w2)
exec(command, *args)
# todo: should I care closing w1+w2 correctly?
end
w1.close; w2.close
status = Process.waitpid2(pid, 0)
# wait until EOF on both pipes (r1+r2)
thread.join
r1.close; r2.close
#$? = status[1] # not possible
(status[1] == 0) ? true : false
end
There is also some unittesting of this 'Kernel#system' replacement:
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/metaeditor/experiments/cpp_embed_ruby/test/output/testall.rb
Code for the sandbox:
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/metaeditor/experiments/cpp_embed_ruby/test/output/b.rb
--
Simon Strandgaard