Using rdebug script
You run your application with rdebug and use -m command line option:
# rdebug -m script_name
For example,
$ cat t.rb
def t1
raise 'test'
end
def t2
t1
end
t2
$ rdebug -m t.rb
./t.rb:1: def t1
(rdb:1) c
./t.rb:2: raise 'test'
(rdb:post-mortem) l=
[-3, 6] in ./t.rb
1 def t1
=> 2 raise 'test'
3 end
4 def t2
5 t1
6 end
(rdb:post-mortem)
Notice the new post-mortem prompt. It indicates that at this point you can't use any stepping commands other than [cont]inue. All other commands are still available, so you can [eval]uate an expression in this context, move up* and *down the stack, etc.
Explicit activation of post-mortem debugging
You can activate the post-mortem mode with Debugger.post_mortem method from your script:
$ cat t.rb
require 'rubygems'
require 'ruby-debug'
Debugger.start
Debugger.post_mortem
def t1
raise 'test'
end
def t2
t1
end
t2
$ ruby t.rb
t.rb:8: raise 'test'
(rdb:post-mortem) l=
[3, 12] in t.rb
3
4 Debugger.start
5 Debugger.post_mortem
6
7 def t1
=> 8 raise 'test'
9 end
10 def t2
11 t1
12 end
(rdb:post-mortem)
Note of caution: Debugger.post_mortem method installs a special at_exit hook. So if your application exits by calling Kernel#exit! method, the debugger is not activated! Be careful.
Local post-mortem debugging
All previous examples describe the case when an application exits without handling an exception. What happens if we've got a peculiar block of code that is not supposed to raise any exceptions, yet, contrary to all expectations, it still does. Debugger.post_mortem method accepts a block of code and activates the post-mortem mode when it executes it.
$ cat t.rb
require 'rubygems'
require 'ruby-debug'
Debugger.start
def t1
raise 'test'
end
def t2
t1
end
begin
Debugger.post_mortem do
t2
end
rescue
debugger
puts 'handled'
end
$ ruby t.rb
t.rb:7: raise 'test'
(rdb:post-mortem) l=
[2, 11] in t.rb
2 require 'ruby-debug'
3
4 Debugger.start
5
6 def t1
=> 7 raise 'test'
8 end
9 def t2
10 t1
11 end
(rdb:post-mortem) c
t.rb:19: puts 'handled'
(rdb:1) l=
[14, 23] in t.rb
14 Debugger.post_mortem do
15 t2
16 end
17 rescue
18 debugger
=> 19 puts 'handled'
20 end
(rdb:1) c
handled
$
Notice that the debugger is still activated when we finished with post-mortem breakpoint.
Source code reloading
Another feature that has been implemented in the latest versions is the source code reloading. This feature is very useful when you debug your Rails application in development mode. You start your application, you make some changes, you hit your browser's Refresh button and you are done with it. No need to restart your mongrel all the time.
So wouldn't it be nice if ruby-debug also be able to reflect all these code changes instead of displaying stale source code?
By entering reload command, you can instruct the debugger to refresh all source code it's aware of. You can also automate this process by using reload on command. In this case, the debugger will be checking the file timestamp and reload the file if it's been updated automatically.
New irb command (experimental)
Evan Weaver popped the question in his blog:
It would be nice to be able to drop into an IRB instance, too, but I don’t know how to do that.
Enter irb command - it activates an irb instance with the current frame's binding. This feature is somewhat experimental and is not available in remote mode. (I wasn't able to install my own input method in order to redirect standard IO).
That's it for now. Enjoy.
WOW! :-O
Post-mortem debugging is simply brilliant! It feels like the next killer innovation for Ruby.
Kudos to you, sir! :-)
I posted a mention about this brilliant innovation on ruby-talk:
http://www.ruby-forum.com/topic/91961
Hope you don’t mind. :-)
Suraj,
Thank you for bug reports!
Any plans on releasing a new 0.5.2 gem with the bug fixes? :-)
Wicked cool.
Suraj,
I’ve just uploaded a new version.
Thanks for the release, Kent.
Now all I need is to somehow configure Test::Unit and rSpec to raise assertion-failed exceptions—so that ruby-debug with post-mortem mode can come to the rescue.
Can someone please explain what is the difference between post-mortem debugging and MS Visual Studio asking to “Break” on an exeption in Debug mode ?
Thanks, this looks like a great tool. One thing though – I can get regular debugging to work in Rails (using webrick), and I can get postmortem debugging to work in a non-Rails Ruby app, but I cannot get postmortem to work in Rails, either with local or remote debugging. Webrick is interrupted initially for me to ‘continue’ it from a debugger prompt, but then when the rails app throws an exception, it’s just tossed to the web browser to display, and nothing comes up in the webrick console window.
Am I doing something wrong? Thanks!
Noah,
You can use post_mortem Rails plugin for that.
This is one revolutionary piece of software. I just found an unhandled exception that would have taken me literally hours to track down. Thanks K!
Thanks for the excellent work and resource. Nice work on top of that.
Just want to express gratitude for information.