module MultiTimeout

Constants

TICK
VALID_SIGNAL
VERSION

Public Class Methods

run(command, timeouts: nil) click to toggle source
# File lib/multi_timeout.rb, line 9
def run(command, timeouts: nil)
  # spawn process in a separate group so we can take it down completely and not leave any children
  pid = Process.spawn({}, *command, pgroup: true)
  gid = Process.getpgid(pid)

  Thread.new do
    elapsed = 0
    loop do
      break if dead?(pid)

      timeouts.each do |signal, max|
        if elapsed >= max
          timeouts.delete(signal)
          puts "Killing '#{truncate(Array(command).join(" "), 30)}' with signal #{signal} after #{elapsed} seconds"
          Process.kill(signal, -gid)
        end
      end
      elapsed += TICK
      sleep TICK
    end
  end

  Process.wait2(pid).last.exitstatus || 1
end

Private Class Methods

dead?(pid) click to toggle source
# File lib/multi_timeout.rb, line 44
def dead?(pid)
  Process.getpgid(pid)
  false
rescue Errno::ESRCH
  true
end
truncate(string, count) click to toggle source
# File lib/multi_timeout.rb, line 36
def truncate(string, count)
  if string.size > count
    string.slice(0, count-3) + "..."
  else
    string
  end
end