Class: Heroku::Executor

Inherits:
Object
  • Object
show all
Defined in:
lib/heroku/executor.rb

Defined Under Namespace

Classes: Terminate

Class Method Summary collapse

Class Method Details

.run(cmd, options = {}, &block) ⇒ Object

Executes a command and yields output line-by-line.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/heroku/executor.rb', line 16

def run(cmd, options = {}, &block)
  lines = []
  running_pid = nil
  logger = options[:logger]
  logger.debug "Running: #{cmd}" if logger
  PTY.spawn(cmd) do |r, w, pid|
    running_pid = pid
    logger.debug "Started: #{pid}" if logger
    terminated = false
    begin
      r.sync = true
      read_from(r, pid, options, lines, &block)
    rescue Heroku::Executor::Terminate => e
      logger.debug "Waiting: #{e.timeout} second(s) to terminate #{pid}" if logger
      terminate_process! pid, e.timeout
      terminated = true
    rescue Errno::EIO, IOError => e
      # ignore
    rescue PTY::ChildExited => e
      logger.debug "Terminated: #{pid}" if logger
      terminated = true
      raise e
    ensure
      unless terminated
        # wait for process
        logger.debug "Waiting: #{pid}" if logger
        ::Process.wait(pid)
      end
    end
  end
  check_exit_status! cmd, running_pid, $?.exitstatus, lines
  lines
rescue Errno::ECHILD => e
  check_exit_status! cmd, running_pid, $?.exitstatus, lines
  lines
rescue PTY::ChildExited => e
  check_exit_status! cmd, running_pid, $!.status.exitstatus, lines
  lines
rescue Heroku::Commander::Errors::Base => e
  logger.debug "Error: #{e.problem}" if logger
  raise
rescue Exception => e
  logger.debug "#{e.class}: #{e.respond_to?(:problem) ? e.problem : e.message}" if logger
  raise Heroku::Commander::Errors::CommandError.new({
    :cmd => cmd,
    :pid => running_pid,
    :status => $?.exitstatus,
    :message => e.message,
    :inner_exception => e,
    :lines => lines
  })
end