2

I was just thinking about how great it would be to be able to run a program and then hit a keystroke to invoke pry and debug. Maybe there is a gem out there that injects binding.pry dynamically during runtime that I don't know about. If there isn't, how would you make a keystroke that inserts binding.pry before the next line of ruby script that is about to execute?

orde
  • 5,233
  • 6
  • 31
  • 33
David West
  • 2,256
  • 6
  • 32
  • 62
  • How would that even happen? The input handler would have to - by necessity - be running in a separate thread from your "main" code in order to process input while the program is running. Have you looked at gdb? – Chris Heald Oct 15 '14 at 15:32

1 Answers1

4

Assuming a POSIX OS, you could try adding a signal handler in your ruby program. The ruby documentation even gives an example of your use case:

.. your process may trap the USR1 signal and use it to toggle debugging (http://www.ruby-doc.org/core-2.1.3/Signal.html)

Signal.trap('USR1') do
  binding.pry
end

Then, to send the signal:

kill -s SIGUSR1 [pid]

Edit: A more complete example: application.rb

My naïve suggestion above will fail with a ThreadError: current thread not owner. Here's a better example using a global $debug flag.

#!/usr/bin/env ruby

require 'pry'

$debug = false
Signal.trap('USR1') do
  puts 'trapped USR1'
  $debug = true
end

class Application
  def run
    while true
      print '.'
      sleep 5
      binding.pry if $debug
    end
  end
end

Application.new.run

This seems to work best when application.rb is running in the foreground in one shell, and you send the SIGUSR1 signal from a separate shell.

Tested in Mac OS 10.9.5. YMMV.

Jared Beck
  • 16,796
  • 9
  • 72
  • 97
  • I'm getting `unsupported signal SIGUSR1 (ArgumentError)`. I am running Cygwin, though. It is supposed to at least be partially POSIX compliant. When I type `kill -l` at the prompt, `30) SIGUSR1` is an option. Also, I haven't been able to understand where to put this. I'm running a Cucumber test suite. I threw it in the `hooks.rb` file -- if that means anything to you! Thanks :) – David West Oct 15 '14 at 21:15
  • Must be my setup... From `irb` I type `Signal.list`, I got back `{"EXIT"=>0, "INT"=>2, "ILL"=>4, "ABRT"=>22, "FPE"=>8, "KILL"=>9, "SEGV"=>11, "TERM"=>15}`. So I've only got a subset of all of the POSIX signals. – David West Oct 15 '14 at 21:18
  • For fun, see if you can co-opt one of the signals for your own purposes. However, I don't recommend co-opting INT, TERM, or SEGV, and you probably can't co-opt KILL. – Jared Beck Oct 15 '14 at 21:37
  • First update, I tried SIGINT. It actually did kinda work in that it popped me into a pry shell. It obviously terminated my process. Then i realized I wasn't running irb or cucumber from the cygwin shell. When i ran irb from cygwin all the signals were available. More tomorrow – David West Oct 16 '14 at 01:58
  • Thanks for the edit. I was about to write that I thought there needed to be more to it! Now I'm thinking about how to run this with a cucumber suite. – David West Oct 17 '14 at 12:21