Class: Subexec
- Inherits:
-
Object
- Object
- Subexec
- Defined in:
- lib/subexec.rb
Overview
Subexec
-
by Peter Kieltyka
Description
Subexec is a simple library that spawns an external command with an optional timeout parameter. It relies on Ruby 1.9’s Process.spawn method. Also, it works with synchronous and asynchronous code.
Useful for libraries that are Ruby wrappers for CLI’s. For example, resizing images with ImageMagick’s mogrify command sometimes stalls and never returns control back to the original process. Subexec executes mogrify and preempts if gets lost.
Usage
# Print hello sub = Subexec.run “echo ‘hello’ && sleep 3”, :timeout => 5 puts sub.output # returns: hello puts sub.exitstatus # returns: 0
# Timeout process after a second sub = Subexec.run “echo ‘hello’ && sleep 3”, :timeout => 1 puts sub.output # returns: puts sub.exitstatus # returns:
Instance Attribute Summary collapse
-
#command ⇒ Object
Returns the value of attribute command.
-
#exitstatus ⇒ Object
Returns the value of attribute exitstatus.
-
#output ⇒ Object
Returns the value of attribute output.
-
#pid ⇒ Object
Returns the value of attribute pid.
-
#timeout ⇒ Object
Returns the value of attribute timeout.
-
#timer ⇒ Object
Returns the value of attribute timer.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(command, options = {}) ⇒ Subexec
constructor
A new instance of Subexec.
- #run! ⇒ Object
Constructor Details
#initialize(command, options = {}) ⇒ Subexec
Returns a new instance of Subexec.
41 42 43 44 45 |
# File 'lib/subexec.rb', line 41 def initialize(command, ={}) self.command = command self.timeout = [:timeout] || -1 # default is to never timeout run! end |
Instance Attribute Details
#command ⇒ Object
Returns the value of attribute command.
31 32 33 |
# File 'lib/subexec.rb', line 31 def command @command end |
#exitstatus ⇒ Object
Returns the value of attribute exitstatus.
35 36 37 |
# File 'lib/subexec.rb', line 35 def exitstatus @exitstatus end |
#output ⇒ Object
Returns the value of attribute output.
34 35 36 |
# File 'lib/subexec.rb', line 34 def output @output end |
#pid ⇒ Object
Returns the value of attribute pid.
30 31 32 |
# File 'lib/subexec.rb', line 30 def pid @pid end |
#timeout ⇒ Object
Returns the value of attribute timeout.
32 33 34 |
# File 'lib/subexec.rb', line 32 def timeout @timeout end |
#timer ⇒ Object
Returns the value of attribute timer.
33 34 35 |
# File 'lib/subexec.rb', line 33 def timer @timer end |
Class Method Details
.run(command, options = {}) ⇒ Object
37 38 39 |
# File 'lib/subexec.rb', line 37 def self.run(command, ={}) new(command, ) end |
Instance Method Details
#run! ⇒ Object
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 78 79 80 81 82 83 |
# File 'lib/subexec.rb', line 47 def run! r, w = IO.pipe self.pid = Process.spawn(command, STDERR=>STDOUT, STDOUT=>w) w.close self.timer = Time.now + timeout timed_out = false loop do begin flags = (timeout > 0 ? Process::WUNTRACED|Process::WNOHANG : 0) ret = Process.waitpid(pid, flags) rescue Errno::ECHILD break end break if ret == pid sleep 0.001 if Time.now > timer timed_out = true break end end if timed_out # The subprocess timed out -- kill it Process.kill(9, pid) rescue Errno::ESRCH self.exitstatus = nil else # The subprocess exited on its own self.exitstatus = $?.exitstatus self.output = r.readlines.join("") end r.close self end |