class Servolux::Child


def alive?


Returns +true+ if the child process is alive.
def alive?
  return if @io.nil?
  Process.kill(0, @pid)
  true
rescue Errno::ESRCH, Errno::ENOENT
  false
end

def initialize( command, opts = {} )


def initialize( command, opts = {} )
  @command = command
  @timeout = opts.getopt :timeout
  @signals = opts.getopt :signals, %w[TERM QUIT KILL]
  @suspend = opts.getopt :suspend, 4
  @io = @pid = @thread = @timed_out = nil
end

def kill


def kill
  return if @io.nil?
  existed = false
  @signals.each do |sig|
    begin
      Process.kill sig, @pid
      existed = true
    rescue Errno::ESRCH, Errno::ENOENT
      return(existed ? nil : true)
    end
    return true unless alive?
    sleep @suspend
    return true unless alive?
  end
  return !alive?
end

def start( mode = 'r', &block )


def start( mode = 'r', &block )
  start_timeout_thread if @timeout
  @io  = IO::popen @command, mode
  @pid = @io.pid
  return block.call(@io) unless block.nil?
  self
end

def start_timeout_thread


def start_timeout_thread
  @timed_out = false
  @thread = Thread.new(self) { |child|
    sleep @timeout
    unless Thread.current[:stop]
      if child.alive?
        child.instance_variable_set(:@timed_out, true)
        child.__send__(:kill)
      end
    end
  }
end

def stop


def stop
  unless @thread.nil?
    t, @thread = @thread, nil
    t[:stop] = true
    t.wakeup.join if t.status
  end
  kill if alive?
  @io.close rescue nil
  @io = @pid = nil
  self
end

def timed_out?


Returns +true+ if the child process was killed by the timeout thread.
def timed_out?
  @timed_out
end

def wait( flags = 0 )


information on the child process.
global variable $? is set to a Process::Status object containing
Waits for the child process to exit and returns its exit status. The
def wait( flags = 0 )
  return if @io.nil?
  Process.wait(@pid, flags)
  $?.exitstatus
end