Ruby on Rails
HowtoDebugWithBreakpoint

Note: Breakpointer has pretty much been deprecated as far as I can tell (Rails Changeset 6611). Use Ruby Debug, as it is much more robust and should be incorporated into Rails 2.0. – Adam G.

What are breakpoints

Breakpoints allow you to step into a running program and poke around its innards from a Rails-included “breakpointer” client. This ability is great for both debugging and code exploration.

Specifically, a breakpoint will pop up in an interactive ruby(irb) session at a pre-defined break point in a Ruby application—it will pop up from within a standard terminal or shell window.

This tutorial describes how to use the built in breakpoint (which uses irb). For explanation of how to use rdebug see HowtoDebugWithRubyDebug.

Getting Started

Creating a breakpoint

In the location of your program that you want to inspect place the following code:

breakpoint

No, really, that’s it.

Working with your breakpoint

When the program runs into the breakpoint statement it will try to get to an irb session. If you’re running the Rails breakpointer client (see below), through an interactive ruby session you can inspect all of the objects that exist where breakpoint was called.

If you are using a breakpoint outside of testing, see the section below for instructions on how to setup a breakpoint client.
Quick tips:

You can also use breakpoints directly from the error screens you get when an unhandled exception occurs somewhere in your application code. Just hit the “Retry with breakpoint” link and fire up the breakpoint client.

Using Breakpoints in tests

When your test isn’t working and you’re not sure why, don’t you just wish you had a crystal ball that could see right into your code, inspect every object in sight and coerce all the variables in the land? Well guess what? We’re fresh out of crystal balls! Fortunately for you, breakpoints are totally up to the job!

Breakpoints work well with unit tests because the tests set up the sample data, and the breakpoint allows you to see what’s happening inside your application; i.e. why it’s not working.

How to do it

Inside your cryptic test, place the breakpoint method. You can give the breakpoint a name or message if you like (it’s optional).

def test_complex_stuff
  @david.projects << @new_project
  breakpoint "Let's have a closer look at @david" 
end

When this program is run and the breakpoint is reached the server connects to the running breakpointer client, starting a new debugging session. In that irb session you can poke and prod all the suspect objects and methods to determine their exact states and operations.

The breakpoint statement need not be in the test. It can be anywhere in your application. Put it in the context you need to investigate.

[ @todo Paste in good example of irb session ]

Using breakpoints in a live application

Breakpoints can be inserted into your application code as well. This allows you to freeze the excution of your entire application and interrogate it at any step along the way.

Breakpoints can go anywhere: in the models, the controllers, or even the views!

When the breakpoint is encountered, Rails establishes a connection between the server and a breakpoint client. During development the client and the server are likely to both be on the same machine, but the breakpoint server can connect with a remote client as well.

Connecting with the breakpoint client

Once you’ve set a breakpoint or twelve in your Rails application, you might try to run your code and wonder, “How do I access this elusive IRB prompt?” Here’s the answer:
  1. open a new shell/terminal session; this shell will become your debugger window
  2. change directory to your Rails application: cd /path/to/your/app
  3. execute the breakpoint script: ./script/breakpointer (windows: ruby script/breakpointer)
  4. now when you run your Rails code, this script will hand you control at each breakpoint.
  5. when finished with inspecting the code at the breakpoint, just type exit at the irb prompt.

Breakpoints can be used remotely over sockets. This means that you debug a remote CGI application, or tunnel the connection over SSH to get through a firewall.

(NB: when you execute the breakpoint script, it will display something that possibly “looks” like an error:

bash-3.00$ ./script/breakpointer                                     
No connection to breakpoint service at druby://localhost:42531 (DRb::DRbConnError)
Tries to connect will be made every 2 seconds...

Don’t be worried! It’s fine and only says that the script is waiting for an incoming connection from your breakpointed application.)

(NB: by default, the development environment is configured to support druby breakpointing, but not the production environment.
If you need this for some reason, you can append

BREAKPOINT_SERVER_PORT=42531

to the end of environments/production.rb)

Changing the server and client settings

./script/breakpointer -h gives the command line options to change the client settings.
Usage: ruby breakpointer [options] [server uri]

This tool lets you connect to a breakpoint service
which was started via Breakpoint.activate_drb.

The server uri defaults to druby://localhost:42531

    -c, --client-uri=uri             Run the client on the specified uri.
                                     This can be used to specify the port
                                     that the client uses to allow for back
                                     connections from the server.
                                     Default: Find a good URI automatically.
                                     Example: -c druby://localhost:12345
    -s, --server-uri=uri             Connect to the server specified at the
                                     specified uri.
                                     Default: druby://localhost:42531
    -v, --verbose                    Report all connections and disconnections
                                     Default: false
    -R, --retry-delay=delay          Automatically try to reconnect to the
                                     server after delay seconds when the
                                     connection failed or timed out.
                                     A value of 0 disables automatical
                                     reconnecting completely.
                                     Default: 10

    -h, --help                       Show this help message. 

[ @todo Explain how to put default settings(client and server) into environment files]

A newer (apparently faster) alternative to “breakpoint” is using ruby-debug which allows you to see the source code of your original application, etc.

Older Rails

Older versions of Rails(eg. 0.8.5) required a seperate libary(dev-utils) to facilitate breakpoints. If you are using such a version you need to install dev-utils yourself for this function to work (“gem install dev-utils“). Note that older versions do not support breakpoints outside of tests.

Other Resources

For further information you may be interested in:
  1. official homepage of the stand-alone ruby-breakpoint library
  2. breakpoint API documentation
  3. breakpoint source code: railties/lib/breakpoint.rb
  4. tips for getting prettier data
  1. the Rails README offers a brief introduction to breakpoints

Troubleshooting

Have a look at the Frequently Asked Questions page at the ruby-breakpoint Wiki


Timeout/Application Error:
If breakpointing works for you, but the script times out after half a minute or so, you might have to put this into your Apache’s httpd.conf:

FastCgiConfig -idle-timeout 320

(makes fast-cgi scripts timeout after 5 mins instead of 1/2 a min)

I can’t get it to work. The terminal gives me:

./script/breakpointer
No connection to breakpoint service at druby://localhost:42531 (DRb::DRb\ConnError)
Tries to connect will be made every 3 seconds…

I am using Mac OS X, and rails 0.9.5

Il Doge

Try invoking the breakpointer like this:

./script/breakpointer --client-uri=druby://localhost:42532

The breakpoint client right will prefer the public network interface to the local one leading to the above problem—this can be fixed by manually specifying the client-uri as in the example above. In the future the breakpoint client will do a better job at guessing it.

—Florian Gross

Same thing:

 ./script/breakpointer --client-uri=druby://localhost:42532
No connection to breakpoint service at druby://localhost:42531 (DRb::DRbConnError)
Tries to connect will be made every 2 seconds...

Il Doge

Are you using the DMG installer or Ruby 1.8.1? BTW, it’s probably best to continue this via private mail—I’m reachable via flgr@ccan.de

Hi, I don’t know why continue by e-mail.
Now I have the same problem and don’t know the answer, can you post here how you resolve this?

Thank you!
Pedro Valentini

Pedro, I was having the same problem. I found the problem was my fault. If your problem was the same as mine, I was trying to run the breakpoint client before running my application. I found I had to put the breakpoint in my code, run the application and THEN run the breakpoint client. Hope this helps.

I was trying to solve this via private mail as then I would not forgot to check back to the discussion as easily. You can of course also submit this as a bug report on the ruby-breakpoint page, but I’m not trying to hide bugs or something like that, but it is hard for me to watch a page on a Wiki and I expect that it will be similar for you as well thus delaying communication even more.

FlorianGross

For anyone with the “No connection to breakpoint service” error

For whatever reason, I could only run the breakpointer in the development environment. I don’t doubt it will run in test, but if you are looking to get to debugging quickly, try to do it from development. Follow these steps:

  1. Insert breakpoints into your code
    breakpoint
  2. Start the server via command line/console/whatever you use
    ./script/server

    or
    ruby script/server
  3. Start the breakpointer
    ./script/breakpointer

    or
    ruby script/breakpointer
  4. Load the browser page of your app

Note: you can also do this in order of steps 2, 1, 4, 3 (swap 1 & 2 or 3 & 4). If you load up the web page before starting the breakpointer it will hang and wait with an hourglass cursor until you start the breakpointer script and tell it to continue (ctrl+d)


It seems that, on OS X, the breakpoint server decides to only listen on IPv6, and the breakpoint client will only connect on IPv4. Then, when the server tries to connect back to the client, it first tries the IPv6 network address of the primary interace…

Anyway, the workaround is as follows. First:

sudo ip6 -d lo0

will disable IPv6 on the loopback interface.

Then

./script/breakpointer --client-uri=druby://localhost:12345

will ensure that the breakpointer uses IPv4 over the loopback interface in both directions.

—Pete Yandell

I am trying to use the a breakpoint in a controller but when it hits a breakpoint the app does nothing. It is during a page transition and it does not proceed to the next page, it does not bring up an irb session and it does not process anything any further. I simply hangs up the browser. I am running this on Win2000.

—Ken Fettig

Bath and Shower
Fragrance
Gift Sets
Hair Care
Makeup
Men’s Grooming
Shaving and Hair Removal
Skin Care
Tools and Accessories

Computers – Computer Add-Ons
Computers – Desktops
Computers – Handhelds & PDAs
Computers – Notebooks

Baby Diapering
Baby Feeding
For Moms
Baby Furniture
Baby Gear
Baby Gifts
Baby Health & Baby Care
Nursery Décor
Potty Training
Baby Safety
Baby Strollers

The ip6 fix did not work for me on OS X. However, replacing localhost with 127.0.0.1 seems to do the trick.

./script/breakpointer -c druby://127.0.0.1:42531

—Keith Morrison

Using multiple webrick/breakpointers

We are trying to work on a linux server at different projects at the same time. We are running multiple instances of webrick using the -p option (-p3001, -p3002, ...), but we can’t get breakpointer to work with the individual webrick servers. When starting multiple breakpointers, it seems that every breakpoint is picked up by a random breakpointer process. We tried using the -c and -s option, but somehow it’s not clear to us how to get things working.

Anyone knowing how to solve this problem?
Thanks!

Today we got an answer from Florian Gross!!

Basically this should work if you change the drb://-url that Rails uses to call Breakpoint.activate_drb() to a different one for each webrick server. The easiest way of doing that is to modify the BREAKPOINT_SERVER_PORT constant in your application’s environment file.

You will then need to specify the server to connect to to breakpointer via the -s option. You shouldn’t need to supply -c in this case.

Hope this helps!

Kind regards,
Florian Gross

in environment.rb:

BREAKPOINT_SERVER_PORT = 42532

in your shell:

script/breakpointer -s druby://127.0.0.1:42532

Thus, every project needs it’s own port.

—Mark de Haan

category:Howto