ruby-debug 0.7 released

Posted on February 02, 2007

I'm happy to announce that ruby-debug 0.7 is available now.

This is mostly a bugfix release. It also has many internal changes that greatly improve the debugger performance. It is so much faster now, that sometime I don't even notice that I'm using it when I start mongrel with rdebug script. The list of changes includes:

  • Frame class has been removed and instead a preallocated block of memory is used to keep frames information. This change has decreased the number of object being created.
  • Another major change involves the fact that the debugger by default doesn't create Binding object for each frame. This is a very expensive operation and it's been the major source of performance problems. Instead, ruby-debug keeps references to the live Ruby's data structures that store information about the local context (ruby_scope). It's still possible to restore the old behavior by using --keep-frame-binding option, or Debugger.keep_frame_binding = true.
  • New set command has been introduced. You can use help set command to see what options are available.

Enjoy, and please report any problem you find!

Comments
  1. gmarikFebruary 02, 2007 @ 06:34 AM

    Cool! Just tried it and it works...! That's what i was looking for, thank you!

    And here are few issues i've noticed so far. 1.help command(inside debugger console) produces list of commands without any descriptions... 2.I cannot delete breakpoints i set.

    1. If i start rdebug -s ./script/server and then connenct with rdebug -c. Is it possible to set breakpoints inside client session? Cuz seems that it's not possible until i hit a breakpoint, and break into debugger console...
  2. KentFebruary 02, 2007 @ 08:06 AM

    gmarik,

    1. Use help <command> to get the information regarding an individual command.

    2. Use delete <bkp_num> to delete a breakpoint

    3. There are two ways around it:

      • Use -w option when you run ruby-debug in the remote mode. This way when you connect your client, you'll get a chance to set up your breakpoints.
      • While ruby-debug is running, you can connect to the control thread using telnet and you get access to a limited number of commands, e.g.

        $ telnet localhost 8990

  3. evanFebruary 02, 2007 @ 12:01 PM

    Under what situations might we want to use --keep-frame-binding?

  4. gmarikFebruary 02, 2007 @ 12:22 PM

    THat's what i get trying to delete breakpoints. What am i doing wrong? $ rdebug -c Connected. ./script/server:2: require File.dirname(FILE) + '/../config/boot' (rdb:1) b No breakpoints (rdb:1) b StoreController.find_cart Set breakpoint 1 at StoreController:find_cart (rdb:1) b Breakpoints: 1 StoreController:find_cart (rdb:1) del 1 Adjusting would put us beyond the newest (innermost) frame. (rdb:1) delete 1 Adjusting would put us beyond the newest (innermost) frame. (rdb:1) b Breakpoints: 1 StoreController:find_cart (rdb:1) Thanks!

  5. KentFebruary 02, 2007 @ 01:39 PM

    Evan,

    The explanation requires some knowledge of the debugger's internal structure. When a new frame is created, instead of capturing a real Binding (using Kernel#binding), the following information is being collected: the current self object and a hash of locals variables (similar to Kernel#local_variablels).

    Now, when you use eval command, an artificial binding is created using this information. This binding is retrieved from self.instance_eval with the propagation of local variables.

    In most cases everything works as expected, but if you see that eval gives you an unexpected result, you probably should resort to --keep-frame-binding. Notice that in this case ruby-debug will slow down your application considerably (at least 6 times).

  6. KentFebruary 02, 2007 @ 01:55 PM

    gmarik,

    I can't reproduce it, but I think I know where the problem is. I've just pushed a new version to rubyforge. It'll take some time to propagate to servers though.

    Thanks

  7. gmarikFebruary 03, 2007 @ 07:31 AM

    Kent, It works now! Thanks!

  8. rabbleFebruary 04, 2007 @ 06:13 PM

    Hey Kent,

    So i just upgraded to 0.7 and it seems like eval is now broken.

    (rdb:1) e on Exception NameError: undefined local variable or method on' for #<ArticleTest:0x335d024> (rdb:1) eval on Exception NameError: undefined local variable or methodon' for #<articletest:0x335d024> (rdb:1)

    Getting eval working for me was a major bonus for using ruby-debug. It gave ruby-debug the best of both the breakpointer / console world and of the traditional debugger. Am i the only one with it broken?

  9. KentFebruary 04, 2007 @ 09:10 PM

    Hey rabble,

    This is exactly the case where you want to start rdebug with --keep-frame-binding option, or Debugger.keep_frame_binding = true if you require ruby-debug explicitly in your code.

    Also you can try the new build 0.7.3 that I've just uploaded to rubyforge where I've fixed several critical bugs and one of them is related to this issue.

    Let me know if it works for you.

  10. pantarheiFebruary 08, 2007 @ 09:55 AM

    is there a way to set the settings initial on every rdebug start?

    everytime i start rdebug i have to hack: 'set autoeval', 'set autolist', 'r on' into the keyboard. how to load this commands initial?

    automtic reload seems not to work? isn't it? or when is the code reloaded? after a manual 'r' the code is reloaded. but only with sending the 'r' command, nowhere automatically.

    regards

  11. KentFebruary 08, 2007 @ 08:16 PM

    pantarhei,

    The reload issue will be fixed in the next version. Also you will be able to specify the initial set commands in your ~/.rdebugrc file.

  12. pantarheiFebruary 09, 2007 @ 02:46 AM

    thank you kent. but how to set it in the file? trying the commands 'set autolist' will result in an error.

    trying to set: 'autoeval=true' 'autolist=true'

    rdebug starts. but none of the commands is executed.

    'autolist=1' also fails with no result.

    am i too stupid or what is going wrong here?

    btw, i'm on windows if this is interesting.

    regards

  13. KentFebruary 09, 2007 @ 09:14 AM

    pantarhei,

    It works only starting with version 0.7.5

    $ rdebug -v
    ruby-debug 0.7.5
    

    Make sure you have the latest installed.

  14. pantarheiFebruary 09, 2007 @ 11:42 AM

    now it works.. ;)

    thank you so much! great work!

    regards

  15. xFebruary 19, 2007 @ 06:40 AM
    trunk $gdb ruby
    GNU gdb 6.3.50-20050815 (Apple version gdb-573) (Fri Oct 20 15:50:43 GMT 2006)
    Copyright 2004 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
    This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries .... done
    
    (gdb) r `which rdebug` --keep-frame-binding -m `which mongrel_rails` startStarting program: /opt/local/bin/ruby `which rdebug` --keep-frame-binding -m `which mongrel_rails` start
    Reading symbols for shared libraries .+... done
    Reading symbols for shared libraries .... done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries ... done
    /opt/local/bin/mongrel_rails:9: require 'rubygems'
    (rdb:1) c
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    ** Starting Mongrel listening at 0.0.0.0:3000
    ** Starting Rails with development environment...
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    Reading symbols for shared libraries . done
    
    Program received signal EXC_BAD_ACCESS, Could not access memory.
    Reason: KERN_PROTECTION_FAILURE at address: 0x00000028
    0x0009bbce in context_copy_locals ()
    (gdb) bt
    #0  0x0009bbce in context_copy_locals ()
    #1  0x00099ec4 in debug_context_dup ()
    #2  0x0009abfe in debug_event_hook ()
    #3  0x0021f156 in rb_longjmp ()
    #4  0x0021f1b0 in rb_exc_raise ()
    #5  0x00215ea9 in rb_raise ()
    #6  0x00224895 in load_failed ()
    #7  0x00224b59 in rb_require_safe ()
    #8  0x00224558 in rb_f_require ()
    #9  0x00221f6f in call_cfunc ()
    #10 0x0022166f in rb_call0 ()
    #11 0x002225bd in rb_call ()
    #12 0x0021ca2a in rb_eval ()
    #13 0x0021be47 in rb_eval ()
    #14 0x00221c71 in rb_call0 ()
    #15 0x002225bd in rb_call ()
    #16 0x00222b26 in rb_call_super ()
    #17 0x0021ccd8 in rb_eval ()
    #18 0x0021be47 in rb_eval ()
    #19 0x00221c71 in rb_call0 ()
    #20 0x002225bd in rb_call ()
    #21 0x0021ca2a in rb_eval ()
    #22 0x0021be47 in rb_eval ()
    #23 0x0021e90c in module_setup ()
    #24 0x0021e4d8 in rb_eval ()
    #25 0x0021e90c in module_setup ()
    #26 0x0021e4d8 in rb_eval ()
    #27 0x0021821f in eval_node ()
    #28 0x00223ef4 in rb_load ()
    #29 0x00224a34 in rb_require_safe ()
    #30 0x00224558 in rb_f_require ()
    #31 0x00221f6f in call_cfunc ()
    #32 0x0022166f in rb_call0 ()
    #33 0x002225bd in rb_call ()
    #34 0x0021ca2a in rb_eval ()
    #35 0x0021be47 in rb_eval ()
    #36 0x00221c71 in rb_call0 ()
    #37 0x002225bd in rb_call ()
    #38 0x00222b26 in rb_call_super ()
    #39 0x0021ccd8 in rb_eval ()
    #40 0x0021be47 in rb_eval ()
    #41 0x00221c71 in rb_call0 ()
    #42 0x002225bd in rb_call ()
    #43 0x0021ca2a in rb_eval ()
    #44 0x0021821f in eval_node ()
    #45 0x00223ef4 in rb_load ()
    #46 0x00224a34 in rb_require_safe ()
    #47 0x00224558 in rb_f_require ()
    #48 0x00221f6f in call_cfunc ()
    #49 0x0022166f in rb_call0 ()
    #50 0x002225bd in rb_call ()
    #51 0x0021ca2a in rb_eval ()
    #52 0x0021be47 in rb_eval ()
    #53 0x00221c71 in rb_call0 ()
    #54 0x002225bd in rb_call ()
    #55 0x00222b26 in rb_call_super ()
    #56 0x0021ccd8 in rb_eval ()
    #57 0x0021be47 in rb_eval ()
    #58 0x00221c71 in rb_call0 ()
    #59 0x002225bd in rb_call ()
    #60 0x0021ca2a in rb_eval ()
    #61 0x0021821f in eval_node ()
    #62 0x00223ef4 in rb_load ()
    #63 0x00224a34 in rb_require_safe ()
    #64 0x00224558 in rb_f_require ()
    #65 0x00221f6f in call_cfunc ()
    #66 0x0022166f in rb_call0 ()
    #67 0x002225bd in rb_call ()
    #68 0x0021ca2a in rb_eval ()
    #69 0x0021be47 in rb_eval ()
    #70 0x00221c71 in rb_call0 ()
    #71 0x002225bd in rb_call ()
    #72 0x00222b26 in rb_call_super ()
    #73 0x0021ccd8 in rb_eval ()
    #74 0x0021be47 in rb_eval ()
    #75 0x00221c71 in rb_call0 ()
    #76 0x002225bd in rb_call ()
    #77 0x0021ca2a in rb_eval ()
    #78 0x0021821f in eval_node ()
    #79 0x00223ef4 in rb_load ()
    #80 0x00224a34 in rb_require_safe ()
    #81 0x00224558 in rb_f_require ()
    #82 0x00221f6f in call_cfunc ()
    #83 0x0022166f in rb_call0 ()
    #84 0x002225bd in rb_call ()
    #85 0x0021ca2a in rb_eval ()
    #86 0x0021be47 in rb_eval ()
    #87 0x00221c71 in rb_call0 ()
    #88 0x002225bd in rb_call ()
    #89 0x00222b26 in rb_call_super ()
    #90 0x0021ccd8 in rb_eval ()
    #91 0x0021be47 in rb_eval ()
    #92 0x00221c71 in rb_call0 ()
    #93 0x002225bd in rb_call ()
    #94 0x0021ca2a in rb_eval ()
    #95 0x0021821f in eval_node ()
    #96 0x00223ef4 in rb_load ()
    #97 0x00224a34 in rb_require_safe ()
    #98 0x00224558 in rb_f_require ()
    #99 0x00221f6f in call_cfunc ()
    #100 0x0022166f in rb_call0 ()
    #101 0x002225bd in rb_call ()
    #102 0x0021ca2a in rb_eval ()
    #103 0x0021be47 in rb_eval ()
    #104 0x00221c71 in rb_call0 ()
    #105 0x002225bd in rb_call ()
    #106 0x00222b26 in rb_call_super ()
    #107 0x0021ccd8 in rb_eval ()
    #108 0x0021be47 in rb_eval ()
    #109 0x00221c71 in rb_call0 ()
    #110 0x002225bd in rb_call ()
    #111 0x0021ca2a in rb_eval ()
    #112 0x0021fc8b in rb_yield_0 ()
    #113 0x0021ff82 in rb_yield ()
    #114 0x002078f6 in rb_ary_each ()
    #115 0x00221f5b in call_cfunc ()
    #116 0x0022166f in rb_call0 ()
    #117 0x002225bd in rb_call ()
    #118 0x0021c80f in rb_eval ()
    #119 0x0021b9e9 in rb_eval ()
    #120 0x00221c71 in rb_call0 ()
    #121 0x002225bd in rb_call ()
    #122 0x0021ca2a in rb_eval ()
    #123 0x0021fc8b in rb_yield_0 ()
    #124 0x0021ff82 in rb_yield ()
    #125 0x002078f6 in rb_ary_each ()
    #126 0x00221f5b in call_cfunc ()
    #127 0x0022166f in rb_call0 ()
    #128 0x002225bd in rb_call ()
    #129 0x0021c80f in rb_eval ()
    #130 0x0021b9e9 in rb_eval ()
    #131 0x00221c71 in rb_call0 ()
    #132 0x002225bd in rb_call ()
    #133 0x0021c80f in rb_eval ()
    #134 0x00221c71 in rb_call0 ()
    #135 0x002225bd in rb_call ()
    #136 0x0021ca2a in rb_eval ()
    #137 0x00221c71 in rb_call0 ()
    #138 0x002225bd in rb_call ()
    #139 0x0021ca2a in rb_eval ()
    #140 0x0021af39 in rb_eval ()
    #141 0x0021821f in eval_node ()
    #142 0x00223ef4 in rb_load ()
    #143 0x00224a34 in rb_require_safe ()
    #144 0x00224558 in rb_f_require ()
    #145 0x00221f6f in call_cfunc ()
    #146 0x0022166f in rb_call0 ()
    #147 0x002225bd in rb_call ()
    #148 0x0021ca2a in rb_eval ()
    #149 0x0021be47 in rb_eval ()
    #150 0x00221c71 in rb_call0 ()
    #151 0x002225bd in rb_call ()
    #152 0x0021ca2a in rb_eval ()
    #153 0x0021821f in eval_node ()
    #154 0x00223ef4 in rb_load ()
    #155 0x00224a34 in rb_require_safe ()
    #156 0x00224558 in rb_f_require ()
    #157 0x00221f6f in call_cfunc ()
    #158 0x0022166f in rb_call0 ()
    #159 0x002225bd in rb_call ()
    #160 0x0021ca2a in rb_eval ()
    #161 0x0021be47 in rb_eval ()
    #162 0x00221c71 in rb_call0 ()
    #163 0x002225bd in rb_call ()
    #164 0x0021ca2a in rb_eval ()
    #165 0x00221c71 in rb_call0 ()
    #166 0x002225bd in rb_call ()
    #167 0x0021ca2a in rb_eval ()
    #168 0x0021d983 in rb_eval ()
    #169 0x0021c8d2 in rb_eval ()
    #170 0x0021fc8b in rb_yield_0 ()
    #171 0x002270ed in proc_invoke ()
    #172 0x002217ed in rb_call0 ()
    #173 0x0022817f in method_call ()
    #174 0x00221f4d in call_cfunc ()
    #175 0x0022166f in rb_call0 ()
    #176 0x002225bd in rb_call ()
    #177 0x0021c80f in rb_eval ()
    #178 0x00221c71 in rb_call0 ()
    #179 0x002225bd in rb_call ()
    #180 0x0021ca2a in rb_eval ()
    #181 0x0021b9e9 in rb_eval ()
    #182 0x0021fc8b in rb_yield_0 ()
    #183 0x002270ed in proc_invoke ()
    #184 0x002217ed in rb_call0 ()
    #185 0x0022817f in method_call ()
    #186 0x00221f4d in call_cfunc ()
    #187 0x0022166f in rb_call0 ()
    #188 0x002225bd in rb_call ()
    #189 0x0021c80f in rb_eval ()
    #190 0x00221c71 in rb_call0 ()
    #191 0x002225bd in rb_call ()
    #192 0x002229d4 in rb_funcall2 ()
    #193 0x002251ab in rb_obj_call_init ()
    #194 0x0024b12e in rb_class_new_instance ()
    #195 0x00221f4d in call_cfunc ()
    #196 0x0022166f in rb_call0 ()
    #197 0x002225bd in rb_call ()
    #198 0x0021c80f in rb_eval ()
    #199 0x0021b9e9 in rb_eval ()
    #200 0x0021d420 in rb_eval ()
    #201 0x00221c71 in rb_call0 ()
    #202 0x002225bd in rb_call ()
    #203 0x0021c80f in rb_eval ()
    #204 0x00221c71 in rb_call0 ()
    #205 0x002225bd in rb_call ()
    #206 0x0021c80f in rb_eval ()
    #207 0x0021b1cf in rb_eval ()
    #208 0x0021821f in eval_node ()
    #209 0x00223ef4 in rb_load ()
    #210 0x00224182 in rb_f_load ()
    #211 0x00221f4d in call_cfunc ()
    #212 0x0022166f in rb_call0 ()
    #213 0x002225bd in rb_call ()
    #214 0x0021ca2a in rb_eval ()
    #215 0x0021821f in eval_node ()
    #216 0x00223ef4 in rb_load ()
    #217 0x0009b631 in debug_debug_load ()
    #218 0x00221f6f in call_cfunc ()
    #219 0x0022166f in rb_call0 ()
    #220 0x002225bd in rb_call ()
    #221 0x0021c80f in rb_eval ()
    #222 0x0021821f in eval_node ()
    #223 0x00223ef4 in rb_load ()
    #224 0x00224182 in rb_f_load ()
    #225 0x00221f4d in call_cfunc ()
    #226 0x00221722 in rb_call0 ()
    #227 0x002225bd in rb_call ()
    #228 0x0021ca2a in rb_eval ()
    #229 0x0021821f in eval_node ()
    #230 0x00218780 in ruby_exec_internal ()
    #231 0x002187ca in ruby_exec ()
    #232 0x002187f4 in ruby_run ()
    #233 0x00001fad in main ()
    (gdb) 
    
  16. KentFebruary 19, 2007 @ 08:20 AM

    @x: Please, submit bug reports to http://rubyforge.org/tracker/?group_id=1900

    ruby and ruby-debug versions and a small test case that reproduces this bug would be welcome too.

  17. Paul CarewMarch 03, 2007 @ 12:40 AM

    I'm runny RoR under Cygwin. I installed ruby-debug with gem install ruby-debug and choose: option 1: 1. ruby-debug 0.7.5 (mswin32)

    It itsalled without errors, but when I try running rdebug script/server, the following error is reported:

    $ rdebug script/server /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.7.5-mswin32/lib/rubydebug.so: Permission denied - /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.7.5-mswin32/lib/rubydebug.so (LoadError) from /usr/lib/ruby/siteruby/1.8/rubygems/customrequire.rb:32:in require' from /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.7.5-mswin32/lib/ruby-debug.rb:5 from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:ingemoriginalrequire' from /usr/lib/ruby/siteruby/1.8/rubygems/customrequire.rb:32:in require' from /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.7.5-mswin32/bin/rdebug:6 from /usr/bin/rdebug:16:inload' from /usr/bin/rdebug:16

    anyone have any ideas? I've speat about 8 hours searching with google, but with no solution.

    after adding execute permissions to ruby_debug.so with the following cmd: chmod 755 /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.7.5-mswin32/lib/ruby_debug.so

    I now get the following error:

    /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.7.5-mswin32/lib/rubydebug.so: No such file or directory - /usr/lib/ruby/gems/1.8/gems/ruby-debug-0.7.5-mswin32/lib/rubydebug.so (LoadError)

    I've now hit a brick wall.

    Anyone have any ideas? paul@carewcontact.com Thanks

  18. SteveMarch 06, 2007 @ 10:18 PM

    Ruby-debug is awesome. I recently upgraded to 1.8.5 and hit the breakpointer problem for the first time today. Initially I was pretty bummed, but now I'm very excited about 1.8.5 breaking breakpointer because it lead to find and install ruby_debug. This is a far superior solution! Excellent work and thank you very much!

  19. KentMarch 07, 2007 @ 01:21 PM

    Hey Steve,

    Thank you for your support!

  20. weepyMarch 14, 2007 @ 04:22 AM

    Hi I notice that ruby 1.8.6/rails 1.2.3 is out ---- is ruby_debug compatible ?

  21. CameronMarch 14, 2007 @ 08:17 AM

    weepy - not sure about 1.8.6, but i'm running 1.8.5/1.2.3 with no problems.

  22. KentMarch 14, 2007 @ 11:31 AM

    weepy,

    ruby-debug should be working fine with ruby 1.8.6