class TurbotRunner::ScriptRunner
Public Class Methods
new(command, output_file, script_config, options={})
click to toggle source
# File lib/turbot_runner/script_runner.rb, line 9 def initialize(command, output_file, script_config, options={}) @command = command @output_file = output_file @script_config = script_config record_handler = options[:record_handler] || BaseHandler.new # A BaseHandler does nothing @processor = Processor.new(self, script_config, record_handler) @timeout = options[:timeout] || 86_400 end
Public Instance Methods
interrupt()
click to toggle source
# File lib/turbot_runner/script_runner.rb, line 75 def interrupt @interrupted = true end
interrupt_and_mark_as_failed()
click to toggle source
# File lib/turbot_runner/script_runner.rb, line 79 def interrupt_and_mark_as_failed @interrupted = true @failed = true end
run()
click to toggle source
# File lib/turbot_runner/script_runner.rb, line 18 def run Dir.chdir(@script_config[:base_directory]) do begin @interrupted = false @failed = false # Start a thread that spawns a subprocess that runs the script and # redirects the script's output to a file at a known location. script_thread = Thread.new { run_command(@command) } # Wait for the output file to be created, so that we can start to read # from it. begin f = File.open(@output_file, "r") rescue Errno::ENOENT sleep 0.1 retry end # Read from output file buildling up lines byte by byte byte by byte # until either we reach the end of the file and the script has exited, or # @interrupted becomes true. We cannot use IO#readline here because if # only half a line has been synced to the file by the time we read it, # then the incomplete line will be read, causing chaos down the line. line = '' time_of_last_read = Time.now until @interrupted do byte = f.read(1) if byte.nil? if script_thread.alive? sleep 0.1 interrupt_and_mark_as_failed if (Time.now - time_of_last_read) > @timeout else break end elsif byte == "\n" @processor.process(line) time_of_last_read = Time.now line = '' else time_of_last_read = Time.now line << byte end end # script_thread may still be alive if we exited the loop above becuase # @interrupted became true, and so we must kill it. kill_running_processes if script_thread.alive? @failed ? false : script_thread.join.value ensure f.close if f end end end
Private Instance Methods
kill_running_processes()
click to toggle source
# File lib/turbot_runner/script_runner.rb, line 92 def kill_running_processes # Send SIGINT to each process in the current proceess group, having # already ensured that the current process itself ignores the signal. Process.kill('INT', 0) end
run_command(command)
click to toggle source
# File lib/turbot_runner/script_runner.rb, line 85 def run_command(command) system(command) # A nil exitstatus indicates that the script was interrupted. A # termsig of 2 indicates that the script was interrupted by a SIGINT. $?.exitstatus == 0 || ($?.exitstatus.nil? && $?.termsig == 2) end