class PIM::ExecutionGuard::Frame

Attributes

initial_seconds[R]
worker[R]

Public Class Methods

new(worker, initial_seconds, reason_message: nil, script_path: nil) click to toggle source
# File pim.rb, line 688
def initialize(worker, initial_seconds, reason_message: nil, script_path: nil)
  @worker = worker
  @initial_seconds = Float(initial_seconds) unless initial_seconds.nil?
  @reason_message = reason_message
  @script_path = script_path
  # Seconds budget for %{deadline} interpolation (updated by limit_execution)
  @deadline_seconds = @initial_seconds
  @mutex = Mutex.new
  @cv = ConditionVariable.new
  @deadline = (Time.now + @initial_seconds) unless @initial_seconds.nil?
  @stopped = false
  @watchdog = nil
end

Public Instance Methods

deadline() click to toggle source
# File pim.rb, line 702
def deadline
  @mutex.synchronize { @deadline }
end
limit_execution(seconds, reason_message = nil) click to toggle source
# File pim.rb, line 710
def limit_execution(seconds, reason_message = nil)

  seconds = Float(seconds)
  raise ArgumentError, "limit_execution seconds must be > 0, got #{seconds}" unless seconds > 0

  new_deadline = Time.now + seconds
  @mutex.synchronize do
    @deadline = [@deadline, new_deadline].compact.min
    @deadline_seconds = seconds
    @reason_message = reason_message unless reason_message.nil?
    @cv.signal
  end

  raise timeout_error if past_deadline?

end
past_deadline?() click to toggle source
# File pim.rb, line 727
def past_deadline?
  @mutex.synchronize { past_deadline_unlocked? }
end
reason_message() click to toggle source
# File pim.rb, line 706
def reason_message
  @mutex.synchronize { @reason_message }
end
signal_changed() click to toggle source
# File pim.rb, line 748
def signal_changed
  @mutex.synchronize { @cv.signal }
end
start_watchdog() click to toggle source
# File pim.rb, line 731
def start_watchdog
  @watchdog = Thread.new { run_watchdog }
  @watchdog.abort_on_exception = false
end
stop() click to toggle source
# File pim.rb, line 736
def stop
  @mutex.synchronize do
    @stopped = true
    @cv.signal
  end

  if @watchdog && @watchdog.alive? && @watchdog != Thread.current
    @watchdog.join(2)
    @watchdog.kill if @watchdog.alive?
  end
end
timeout_error() click to toggle source
# File pim.rb, line 752
def timeout_error
  message = "execution deadline exceeded"
  script_path, deadline_seconds, reason = nil
  @mutex.synchronize do
    script_path = @script_path
    deadline_seconds = @deadline_seconds
    reason = @reason_message
  end
  unless PIM.is_empty?(reason)
    script_path_text = script_path || 'unknown'
    deadline_text = if deadline_seconds.nil?
                      'unlimited'
                    elsif deadline_seconds == deadline_seconds.to_i
                      deadline_seconds.to_i
                    else
                      deadline_seconds
                    end
    message = "#{message}\n#{reason}" % { script_path: script_path_text, deadline: deadline_text }
  end
  PIM::ExecutionTimeoutError.new(message)
end