Class | SystemUniversal |
In: |
lib/systemu.rb
|
Parent: | Object |
VERSION | = | '1.2.0' unless defined? SystemUniversal::VERSION |
instance methods
# File lib/systemu.rb, line 44 44: def initialize argv, opts = {}, &block 45: getopt = getopts opts 46: 47: @argv = argv 48: @block = block 49: 50: @stdin = getopt[ ['stdin', 'in', '0', 0] ] 51: @stdout = getopt[ ['stdout', 'out', '1', 1] ] 52: @stderr = getopt[ ['stderr', 'err', '2', 2] ] 53: @env = getopt[ 'env' ] 54: @cwd = getopt[ 'cwd' ] 55: 56: @host = getopt[ 'host', self.class.host ] 57: @ppid = getopt[ 'ppid', self.class.ppid ] 58: @pid = getopt[ 'pid', self.class.pid ] 59: @ruby = getopt[ 'ruby', self.class.ruby ] 60: end
# File lib/systemu.rb, line 164 164: def child_program config 165: "PIPE = STDOUT.dup\nbegin\nrequire 'yaml'\n\nconfig = YAML.load(IO.read('\#{ config }'))\n\nargv = config['argv']\nenv = config['env']\ncwd = config['cwd']\nstdin = config['stdin']\nstdout = config['stdout']\nstderr = config['stderr']\n\nDir.chdir cwd if cwd\nenv.each{|k,v| ENV[k.to_s] = v.to_s} if env\n\nSTDIN.reopen stdin\nSTDOUT.reopen stdout\nSTDERR.reopen stderr\n\nPIPE.puts \"pid: \\\#{ Process.pid }\"\nPIPE.flush ### the process is ready yo!\nPIPE.close\n\nexec *argv\nrescue Exception => e\nPIPE.write Marshal.dump(e) rescue nil\nexit 42\nend\n" 166: end
# File lib/systemu.rb, line 126 126: def child_setup tmp 127: stdin = File.expand_path(File.join(tmp, 'stdin')) 128: stdout = File.expand_path(File.join(tmp, 'stdout')) 129: stderr = File.expand_path(File.join(tmp, 'stderr')) 130: program = File.expand_path(File.join(tmp, 'program')) 131: config = File.expand_path(File.join(tmp, 'config')) 132: 133: if @stdin 134: open(stdin, 'w'){|f| relay @stdin => f} 135: else 136: FileUtils.touch stdin 137: end 138: FileUtils.touch stdout 139: FileUtils.touch stderr 140: 141: c = {} 142: c['argv'] = @argv 143: c['env'] = @env 144: c['cwd'] = @cwd 145: c['stdin'] = stdin 146: c['stdout'] = stdout 147: c['stderr'] = stderr 148: c['program'] = program 149: open(config, 'w'){|f| YAML.dump c, f} 150: 151: open(program, 'w'){|f| f.write child_program(config)} 152: 153: c 154: end
# File lib/systemu.rb, line 235 235: def getopts opts = {} 236: lambda do |*args| 237: keys, default, ignored = args 238: catch('opt') do 239: [keys].flatten.each do |key| 240: [key, key.to_s, key.to_s.intern].each do |key| 241: throw 'opt', opts[key] if opts.has_key?(key) 242: end 243: end 244: default 245: end 246: end 247: end
# File lib/systemu.rb, line 115 115: def new_thread cid, block 116: q = Queue.new 117: Thread.new(cid) do |cid| 118: current = Thread.current 119: current.abort_on_exception = true 120: q.push current 121: block.call cid 122: end 123: q.pop 124: end
# File lib/systemu.rb, line 156 156: def quietly 157: v = $VERBOSE 158: $VERBOSE = nil 159: yield 160: ensure 161: $VERBOSE = v 162: end
# File lib/systemu.rb, line 199 199: def relay srcdst 200: src, dst, ignored = srcdst.to_a.first 201: if src.respond_to? 'read' 202: while((buf = src.read(8192))); dst << buf; end 203: else 204: src.each{|buf| dst << buf} 205: end 206: end
# File lib/systemu.rb, line 62 62: def systemu 63: tmpdir do |tmp| 64: c = child_setup tmp 65: status = nil 66: 67: begin 68: thread = nil 69: 70: quietly{ 71: IO.popen "#{ @ruby } #{ c['program'] }", 'r+' do |pipe| 72: line = pipe.gets 73: case line 74: when %r/^pid: \d+$/ 75: cid = Integer line[%r/\d+/] 76: else 77: begin 78: buf = pipe.read 79: buf = "#{ line }#{ buf }" 80: e = Marshal.load buf 81: raise unless Exception === e 82: raise e 83: rescue 84: raise "wtf?\n#{ buf }\n" 85: end 86: end 87: thread = new_thread cid, @block if @block 88: pipe.read rescue nil 89: end 90: } 91: status = $? 92: ensure 93: if thread 94: begin 95: class << status 96: attr 'thread' 97: end 98: status.instance_eval{ @thread = thread } 99: rescue 100: 42 101: end 102: end 103: end 104: 105: if @stdout or @stderr 106: open(c['stdout']){|f| relay f => @stdout} if @stdout 107: open(c['stderr']){|f| relay f => @stderr} if @stderr 108: status 109: else 110: [status, IO.read(c['stdout']), IO.read(c['stderr'])] 111: end 112: end 113: end
# File lib/systemu.rb, line 208 208: def tmpdir d = Dir.tmpdir, max = 42, &b 209: i = -1 and loop{ 210: i += 1 211: 212: tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }" 213: 214: begin 215: Dir.mkdir tmp 216: rescue Errno::EEXIST 217: raise if i >= max 218: next 219: end 220: 221: break( 222: if b 223: begin 224: b.call tmp 225: ensure 226: FileUtils.rm_rf tmp unless SystemU.turd 227: end 228: else 229: tmp 230: end 231: ) 232: } 233: end