class PryJanitor

Constants

ACTIVITY_SIGNAL
CHECK_ACTIVITY_SECONDS
DEFAULT_TIMEOUT_SECONDS
EXIT_SIGNAL
KILL_SIGNAL
PAUSE_SIGNAL
PRY_HOOK_NAME
VERSION

Public Class Methods

auto_exit_after(timeout = DEFAULT_TIMEOUT_SECONDS) click to toggle source
# File lib/pry-janitor.rb, line 17
def self.auto_exit_after(timeout = DEFAULT_TIMEOUT_SECONDS)
  instance.auto_exit_after(timeout)
end
register_pry_hooks() click to toggle source
# File lib/pry-janitor.rb, line 21
def self.register_pry_hooks
  instance.register_pry_hooks
end

Public Instance Methods

auto_exit_after(timeout) click to toggle source
# File lib/pry-janitor.rb, line 25
def auto_exit_after(timeout)
  kill_child
  with_install_handlers do
    @parent_pid = Process.pid
    @child_pid = Process.fork { child_process(timeout) }
  end
  kill_child_on_exit
end
register_pry_hooks() click to toggle source
# File lib/pry-janitor.rb, line 34
def register_pry_hooks
  # pause last activity for long running commands
  Pry.hooks.add_hook(:before_eval, PRY_HOOK_NAME) do
    signal_child(PAUSE_SIGNAL)
  end

  # record activity when a command finishes, line is read, or session starts
  Pry.hooks.add_hook(:after_eval, PRY_HOOK_NAME) do
    signal_child(ACTIVITY_SIGNAL)
  end

  Pry.hooks.add_hook(:after_read, PRY_HOOK_NAME) do
    signal_child(ACTIVITY_SIGNAL)
  end

  Pry.hooks.add_hook(:before_session, PRY_HOOK_NAME) do
    signal_child(ACTIVITY_SIGNAL)
  end
end

Private Instance Methods

child_process(timeout) click to toggle source
# File lib/pry-janitor.rb, line 66
def child_process(timeout)
  loop do
    begin
      # kill parent and exit loop if last activity is longer than timeout
      if @last_activity && @last_activity < Time.now - timeout
        Process.kill(KILL_SIGNAL, @parent_pid)
      end
      sleep CHECK_ACTIVITY_SECONDS
    rescue Interrupt
      # parent exited, exit loop
      break
    end
  end
end
kill_child() click to toggle source
# File lib/pry-janitor.rb, line 85
def kill_child
  signal_child(KILL_SIGNAL)
end
kill_child_on_exit() click to toggle source
# File lib/pry-janitor.rb, line 89
def kill_child_on_exit
  Signal.trap(EXIT_SIGNAL) { kill_child }
end
signal_child(signal) click to toggle source
# File lib/pry-janitor.rb, line 81
def signal_child(signal)
  Process.kill(signal, @child_pid) if @child_pid
end
with_install_handlers() { || ... } click to toggle source
  1. install signal handlers in the parent so the child is immediately ready

  2. re-install pre-existing signal handlers back into the parent

# File lib/pry-janitor.rb, line 58
def with_install_handlers
  prev_sig1 = Signal.trap(ACTIVITY_SIGNAL) { @last_activity = Time.now }
  prev_sig2 = Signal.trap(PAUSE_SIGNAL) { @last_activity = nil }
  yield
  Signal.trap(ACTIVITY_SIGNAL, prev_sig1)
  Signal.trap(PAUSE_SIGNAL, prev_sig2)
end