class Explorer::Process

Attributes

command[R]
env[R]
label[R]
log_watcher[R]
pgid[R]
pid[R]
pipe[R]
state[R]
status[R]
working_dir[R]

Public Class Methods

new(label, command, working_dir: ENV['PWD'], log_watcher: nil, env: {}) click to toggle source

Log watcher should implement a 'log' method which accepts a label and a line of text Log watcher should also be thread-safe or an actor

# File lib/explorer/process.rb, line 12
def initialize(label, command, working_dir: ENV['PWD'], log_watcher: nil, env: {})
  @label = label
  @command = command
  @working_dir = File.expand_path(working_dir)
  @log_watcher = log_watcher
  @env = env
  @state = :stopped
  @status = nil
end

Public Instance Methods

start() click to toggle source
# File lib/explorer/process.rb, line 30
def start
  return Actor.current if @state == :started

  @status = nil
  @pipe, slave = PTY.open
  slave.raw!
  @pid = spawn_process(label, command, working_dir: working_dir, pipe: slave)
  @pgid = ::Process.getpgid(@pid)
  slave.close

  @state = :started
  signal :state_changed

  wait_pid
  async.read_pipe

  return Actor.current
end
started?() click to toggle source
# File lib/explorer/process.rb, line 22
def started?
  @state == :started
end
stop(sig='INT') click to toggle source
# File lib/explorer/process.rb, line 49
def stop(sig='INT')
  return Actor.current if @state == :stopped
  begin
    ::Process.kill(sig, -pgid)
    wait_on_stop
  rescue
  end
  return Actor.current
end
stopped?() click to toggle source
# File lib/explorer/process.rb, line 26
def stopped?
  @state == :stopped
end
wait_on_stop() click to toggle source
# File lib/explorer/process.rb, line 59
def wait_on_stop
  while @state != :stopped
    wait :state_changed
  end
  return Actor.current
end

Private Instance Methods

read_pipe() click to toggle source
# File lib/explorer/process.rb, line 68
def read_pipe
  loop do
    line = @pipe.readline # So we don't fill up the pipe
    log_watcher.log(label, line) if log_watcher
  end
rescue
end
shutdown() click to toggle source
# File lib/explorer/process.rb, line 94
def shutdown
  stop if @state == :started
end
spawn_process(label, command, working_dir: ENV['PWD'], pipe: :out) click to toggle source
# File lib/explorer/process.rb, line 98
def spawn_process(label, command, working_dir: ENV['PWD'], pipe: :out)
  options = {
    chdir: working_dir,
    in: :close,
    out: pipe,
    err: pipe,
    pgroup: true,
    close_others: true,
  }
  Explorer.without_bundler do
    spawn(env, command, options)
  end
end
wait_pid() click to toggle source
# File lib/explorer/process.rb, line 76
def wait_pid
  actor = Actor.current
  Thread.new do
    ::Process.wait(pid)
    actor.send(:wait_pid_done, $?) #Run in actor thread
  end
end
wait_pid_done(status) click to toggle source
# File lib/explorer/process.rb, line 84
def wait_pid_done(status)
  @status = status
  @pid = nil
  @pgid = nil
  @state = :stopped
  signal :state_changed

  Logger.info "Process #{label} exited with #{status}"
end