h2. What are breakpoints

Breakpoints allow you to step into a running program and poke around its innards. This ability is great for both debugging and code exploration.

Specifically, a breakpoint will pop up an interactive ruby(irb) session at a pre-defined break point in a Ruby application.

h2. Getting Started

h3. Creating a breakpoint

In the location of your program that you want to inspect place the following code:

<pre><code>breakpoint</pre></code>

No, really, that's it.

h3. Working with your breakpoint

When the program runs into the @breakpoint@ statement it will try to get to an irb session. In the interactive ruby session you can inspect all of the objects that exist where @breakpoint@ was called.

<div style="border: solid 1px silver; padding: 10px">If you are using a breakpoint outside of testing, see the section below for instructions on how to setup a breakpoint client.</div>

*Quick tips:*
* use CTRL-D (Unix) or CTRL-Z (Windows) or @exit@ to leave the breakpoint and continue running the program
* use @exit!@ to terminate the program from within a breakpoint
* other interesting things to check out include: @local_variables@, @instance_variables@, @caller@, @methods@
* just type the name of your variable to check its value
* Note that you can enter any type of regular Ruby code into a breakpoint IRB shell. You can even hot patch your deployed code to fix a problem at run-time!

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.

h2. 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 _coerse_ all the variables in the land? Well guess what? We're fresh out of crystal balls! Fortunatly 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.

h3. 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).

<pre><code>def test_complex_stuff
  @david.projects << @new_project
  breakpoint "Let's have a closer look at @david" 
end</pre></code>

When this program is run and the @breakpoint@ is reached a new irb session is created. In that irb session you can poke and prod all the suspect objects and methods to determine their exact state and operation.

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.

_If you get strange output running your tests (irb starts and reads the file containing the breakpoint)_
_try adding this line to the top of your testfile:_

<pre><code>def IRB.parse_opts() end</code></pre>

_this has been fixed in Rails 0.10.0.)_

[ @todo Paste in good example of irb session ]

h2. Using breakpoints in a live application

Breakpoints can be inserted into your application code as well. This allows you can 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, 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.

h2. 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:
# open a new shell/terminal session; this shell will become your debugger window
# change directory to your Rails application: <code>cd /path/to/your/app</code>
# execute the breakpoint script: <code>./script/breakpointer</code> (windows: <code>ruby script/breakpointer</code>
# now when you run your Rails code, this script will hand you control at each breakpoint.

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:* 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 <code>environments/production.rb</code>)_

h3. Changing the server and client settings

<code>./script/breakpointer -h</code> gives the command line options to change the client settings.

<pre><code>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. </pre></code>

[ @todo Explain how to put default settings(client and server) into environment files]

h2. 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.

h2. Other Resources

For further information you may be interested in:
# "official homepage of the stand-alone ruby-breakpoint library":http://ruby-breakpoint.rubyforge.org/
# "breakpoint API documentation":http://rails.rubyonrails.com/classes/Breakpoint.html#M000468
# "breakpoint source code: railties/lib/breakpoint.rb":http://dev.rubyonrails.com/file/trunk/railties/lib/breakpoint.rb
# "tips for getting prettier data":http://ruby-breakpoint.rubyforge.org/wiki/wiki.pl?TipsAndTricks

# the Rails README offers a brief introduction to breakpoints

h2. Troubleshooting

Have a look at the "Frequently Asked Questions page at the ruby-breakpoint Wiki":http://ruby-breakpoint.rubyforge.org/wiki/wiki.pl?FrequentlyAskedQuestions

--
<strong>Timeout/Application Error:</strong>
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
<pre>httpd.conf:

FastCgiConfig -idle-timeout 320
</pre>
(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:

<pre><code>./script/breakpointer --client-uri=druby://localhost:42532</code></pre>

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:

<pre><code> ./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...</code></pre>

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

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:
<pre>sudo ip6 -d lo0</pre>
will disable IPv6 on the loopback interface.

Then
<pre>./script/breakpointer --client-uri=druby://localhost:12345</pre>
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


category:Howto
