# File lib/open4.rb, line 155 def background cmd, opts = {} #--{{{ require 'thread' q = Queue.new opts['pid'] = opts[:pid] = q thread = Thread.new(cmd, opts){|cmd, opts| spawn cmd, opts} pid = q.pop sc = class << thread; self; end sc.module_eval { define_method(:pid){ pid } define_method(:spawn_status){ @spawn_status ||= value } define_method(:exitstatus){ spawn_status.exitstatus } } thread #--}}} end
# File lib/open4.rb, line 9 def popen4(*cmd) #--{{{ pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe verbose = $VERBOSE begin $VERBOSE = nil ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) cid = fork { 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 exec(*cmd) raise "exec failed!" rescue Exception => e Marshal.dump(e, ps.last) ps.last.flush end ps.last.close unless (ps.last.closed?) exit! } ensure $VERBOSE = verbose end [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close} begin e = Marshal.load ps.first raise(Exception === e ? e : "unknown failure!") rescue EOFError # If we get an EOF error, then the exec was successful 42 end pw.last.sync = true pi = [pw.last, pr.first, pe.first] if defined? yield begin yield(cid, *pi) Process.waitpid2(cid).last ensure pi.each{|fd| fd.close unless fd.closed?} end else [cid, pw.last, pr.first, pe.first] end #--}}} end
# File lib/open4.rb, line 90 def spawn cmd, opts = {} #--{{{ getopt = lambda do |*args| keys, default, ignored = args catch('opt') do [keys].flatten.each do |key| [key, key.to_s, key.to_s.intern].each do |key| throw 'opt', opts[key] if opts.has_key?(key) end end default end end ignore_exit_failure = getopt[ 'ignore_exit_failure', getopt['quiet', false] ] ignore_exec_failure = getopt[ 'ignore_exec_failure', !getopt['raise', true] ] exitstatus = getopt[ %( exitstatus exit_status status ), 0 ] stdin = getopt[ ['stdin', 'in', '0', 0] ] stdout = getopt[ ['stdout', 'out', '1', 1] ] stderr = getopt[ ['stderr', 'err', '2', 2] ] pid = getopt[ 'pid' ] started = false status = begin popen4(cmd) do |c, i, o, e| started = true if pid.respond_to? '<<' pid << c end it = Thread.new(i,stdin) do |i,stdin| if stdin if stdin.respond_to? :each stdin.each{|buf| i << buf} elsif stdin.respond_to? :read i << stdin.read else i << stdin.to_s end end i.close end ot = Thread.new(o,stdout){|o,stdout| o.each{|buf| stdout << buf if stdout}} et = Thread.new(e,stderr){|e,stderr| e.each{|buf| stderr << buf if stderr}} it.join ot.join if ot et.join if et end rescue raise unless(not started and ignore_exec_failure) end raise SpawnError.new(cmd, status) unless (ignore_exit_failure or (status.nil? and ignore_exec_failure) or (status.exitstatus == exitstatus)) status #--}}} end
Generated with the Darkfish Rdoc Generator 2.