class Shrimple::Process
Attributes
start_time[R]
stop_time[R]
Public Class Methods
new(cmd, inio, outio, errio, timeout=nil)
click to toggle source
runs cmd, passes instr on its stdin, and fills outio and errio with the command’s output.
# File lib/shrimple/process.rb, line 15 def initialize cmd, inio, outio, errio, timeout=nil @start_time = Time.now @chin, @chout, @cherr, @child = Open3.popen3(*cmd) Shrimple.processes._add(self) @chout.binmode @killed = false @timed_out = false @thrin = Thread.new { drain(inio, @chin) } @throut = Thread.new { drain(@chout, outio) } @threrr = Thread.new { drain(@cherr, errio) } # ensure cleanup is called when the child exits. (strange it requires a whole new thread...?) @thrchild = Thread.new { if timeout outatime unless @child.join(timeout) else @child.join end stop } end
Public Instance Methods
_child_thread()
click to toggle source
only meant to be used by the ProcessMonitor
# File lib/shrimple/process.rb, line 83 def _child_thread @child end
_cleanup()
click to toggle source
may only be called once, synchronized by stop()
# File lib/shrimple/process.rb, line 88 def _cleanup raise "Someone else already stopped this process??!!" if @stop_time @stop_time = Time.now end
_deactivate()
click to toggle source
returns true if process was previously active. must be externally synchronized.
# File lib/shrimple/process.rb, line 94 def _deactivate retval = @inactive @inactive = true return !retval end
finished?()
click to toggle source
# File lib/shrimple/process.rb, line 41 def finished? @stop_time != nil end
kill(seconds_until_panic=2)
click to toggle source
kill-o-zaps the phantom process now (using -9 if needed), then waits until it’s truly gone
# File lib/shrimple/process.rb, line 59 def kill seconds_until_panic=2 @killed = true if @child.alive? # rescue because process might have died between previous line and this one ::Process.kill("TERM", @child.pid) rescue Errno::ESRCH end if !@child.join(seconds_until_panic) ::Process.kill("KILL", @child.pid) if @child.alive? end # ensure kill doesn't return until process is truly gone # (there may be a chance of this deadlocking with a blocking callback... not sure) @thrchild.join unless Thread.current == @thrchild end
killed?()
click to toggle source
# File lib/shrimple/process.rb, line 50 def killed? @killed end
stop()
click to toggle source
waits patiently until phantom process terminates, then cleans up
# File lib/shrimple/process.rb, line 74 def stop wait_for_the_end # do all our waiting outside the sync loop Shrimple.processes._remove(self) do _cleanup end end
success?()
click to toggle source
returns false if the process hasn’t finished yet
# File lib/shrimple/process.rb, line 46 def success? finished? && @child.value.success? ? true : false end
timed_out?()
click to toggle source
# File lib/shrimple/process.rb, line 54 def timed_out? @timed_out end
Private Instance Methods
drain(reader, writer)
click to toggle source
reads every last drop, then closes both files. must be threadsafe.
# File lib/shrimple/process.rb, line 113 def drain reader, writer begin # randomly chosen buffer size loop { writer.write(reader.readpartial(256*1024)) } rescue EOFError # not an error # puts "EOF STDOUT" if reader == @chout # puts "EOF STDERR" if reader == @cherr # puts "EOF STDIN #{reader}" if writer == @chin rescue Errno::EPIPE # child was killed, no problem ensure reader.close writer.close rescue Errno::EPIPE end end
outatime()
click to toggle source
# File lib/shrimple/process.rb, line 107 def outatime @timed_out = true kill end
wait_for_the_end()
click to toggle source
# File lib/shrimple/process.rb, line 102 def wait_for_the_end [@thrin, @throut, @threrr, @child].each(&:join) @thrchild.join unless Thread.current == @thrchild end