Module: Open4
- Defined in:
- lib/switchman/open4.rb
Overview
This fixes a bug with exception handling, see github.com/ahoward/open4/pull/30
Class Method Summary collapse
Class Method Details
.do_popen(b = nil, exception_propagation_at = nil, closefds = false, &cmd) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/switchman/open4.rb', line 6 def self.do_popen(b = nil, exception_propagation_at = nil, closefds=false, &cmd) pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe verbose = $VERBOSE begin $VERBOSE = nil cid = fork { if closefds exlist = [0, 1, 2] | [pw,pr,pe,ps].map{|p| [p.first.fileno, p.last.fileno] }.flatten ObjectSpace.each_object(IO){|io| io.close if (not io.closed?) and (not exlist.include? io.fileno) rescue nil } end pw.last.close STDIN.reopen pw.first pw.first.close pr.first.close STDOUT.reopen pr.last pr.last.close pe.first.close STDERR.reopen pe.last pe.last.close STDOUT.sync = STDERR.sync = true begin cmd.call(ps) rescue Exception => e begin Marshal.dump(e, ps.last) ps.last.flush rescue Errno::EPIPE raise e end ensure ps.last.close unless ps.last.closed? end exit! } ensure $VERBOSE = verbose end [ pw.first, pr.last, pe.last, ps.last ].each { |fd| fd.close } Open4.propagate_exception cid, ps.first if exception_propagation_at == :init pw.last.sync = true pi = [ pw.last, pr.first, pe.first ] begin return [cid, *pi] unless b begin b.call(cid, *pi) ensure pi.each { |fd| fd.close unless fd.closed? } end Open4.propagate_exception cid, ps.first if exception_propagation_at == :block Process.waitpid2(cid).last ensure ps.first.close unless ps.first.closed? end end |