![show/hide quicksearch [+]](./images/find.png)
This library provides debugging functionality to Ruby.
To add a debugger to your code, start by requiring debug in your program:
def say(word) require 'debug' puts word end
This will cause Ruby to interrupt execution and show a prompt when the say method is run.
Once you're inside the prompt, you can start debugging your program.
(rdb:1) p word "hello"
You can get help at any time by pressing h.
(rdb:1) h
Debugger help v.-0.002b
Commands
  b[reak] [file:|class:]<line|method>
  b[reak] [class.]<line|method>
                             set breakpoint to some position
  wat[ch] <expression>       set watchpoint to some expression
  cat[ch] (<exception>|off)  set catchpoint to an exception
  b[reak]                    list breakpoints
  cat[ch]                    show catchpoint
  del[ete][ nnn]             delete some or all breakpoints
  disp[lay] <expression>     add expression into display expression list
  undisp[lay][ nnn]          delete one particular or all display expressions
  c[ont]                     run until program ends or hit breakpoint
  s[tep][ nnn]               step (into methods) one line or till line nnn
  n[ext][ nnn]               go over one line or till line nnn
  w[here]                    display frames
  f[rame]                    alias for where
  l[ist][ (-|nn-mm)]         list program, - lists backwards
                             nn-mm lists given lines
  up[ nn]                    move to higher frame
  down[ nn]                  move to lower frame
  fin[ish]                   return to outer frame
  tr[ace] (on|off)           set trace mode of current thread
  tr[ace] (on|off) all       set trace mode of all threads
  q[uit]                     exit from debugger
  v[ar] g[lobal]             show global variables
  v[ar] l[ocal]              show local variables
  v[ar] i[nstance] <object>  show instance variables of object
  v[ar] c[onst] <object>     show constants of object
  m[ethod] i[nstance] <obj>  show methods of object
  m[ethod] <class|module>    show instance methods of class or module
  th[read] l[ist]            list all threads
  th[read] c[ur[rent]]       show current thread
  th[read] [sw[itch]] <nnn>  switch thread context to nnn
  th[read] stop <nnn>        stop thread nnn
  th[read] resume <nnn>      resume thread nnn
  p expression               evaluate expression and print its value
  h[elp]                     print this help
  <everything else>          evaluate
The following is a list of common functionalities that the debugger provides.
In general, a debugger is used to find bugs in your program, which often means pausing execution and inspecting variables at some point in time.
Let's look at an example:
def my_method(foo) require 'debug' foo = get_foo if foo.nil? raise if foo.nil? end
When you run this program, the debugger will kick in just before the foo assignment.
(rdb:1) p foo nil
In this example, it'd be interesting to move to the next line and inspect the value of foo again. You can do that by pressing n:
(rdb:1) n # goes to next line (rdb:1) p foo nil
You now know that the original value of foo was nil, and that it still was nil after calling get_foo.
Other useful commands for navigating through your code are:
c
Runs the program until it either exists or encounters another breakpoint. You usually press c when you are finished debugging your program and want to resume its execution.
s
Steps into method definition. In the previous example, s would take you inside the method definition of get_foo.
r
Restart the program.
q
Quit the program.
You can use the debugger to easily inspect both local and global variables. We've seen how to inspect local variables before:
(rdb:1) p my_arg 42
You can also pretty print the result of variables or expressions:
(rdb:1) pp %w{a very long long array containing many words}
["a",
 "very",
 "long",
 ...
]
You can list all local variables with +v l+:
(rdb:1) v l foo => "hello"
Similarly, you can show all global variables with +v g+:
(rdb:1) v g all global variables
Finally, you can omit p if you simply want to evaluate a variable or expression
(rdb:1) 5**2 25
Ruby Debug provides more advanced functionalities like switching between threads, setting breakpoints and watch expressions, and more. The full list of commands is available at any time by pressing h.
Make sure you remove every instance of +require 'debug'+ before shipping your code. Failing to do so may result in your program hanging unpredictably.
Debug is not available in safe mode.
Returns the list of break points where execution will be stopped.
See DEBUGGER__ for more usage
 
               # File debug.rb, line 916
def break_points
  @break_points
end
             
             
               # File debug.rb, line 970
def context(thread=Thread.current)
  c = thread[:__debugger_data__]
  unless c
    thread[:__debugger_data__] = c = Context.new
  end
  c
end
             
             
               # File debug.rb, line 1049
def debug_thread_info(input, binding)
  case input
  when /^l(?:ist)?/
    make_thread_list
    thread_list_all
  when /^c(?:ur(?:rent)?)?$/
    make_thread_list
    thread_list(@thread_list[Thread.current])
  when /^(?:sw(?:itch)?\s+)?(\d+)/
    make_thread_list
    th = get_thread($1.to_i)
    if th == Thread.current
      @stdout.print "It's the current thread.\n"
    else
      thread_list(@thread_list[th])
      context(th).stop_next
      th.run
      return :cont
    end
  when /^stop\s+(\d+)/
    make_thread_list
    th = get_thread($1.to_i)
    if th == Thread.current
      @stdout.print "It's the current thread.\n"
    elsif th.stop?
      @stdout.print "Already stopped.\n"
    else
      thread_list(@thread_list[th])
      context(th).suspend
    end
  when /^resume\s+(\d+)/
    make_thread_list
    th = get_thread($1.to_i)
    if th == Thread.current
      @stdout.print "It's the current thread.\n"
    elsif !th.stop?
      @stdout.print "Already running."
    else
      thread_list(@thread_list[th])
      th.run
    end
  end
end
             
            Returns the display expression list
See DEBUGGER__ for more usage
 
               # File debug.rb, line 909
def display
  @display
end
             
             
               # File debug.rb, line 982
def get_thread(num)
  th = @thread_list.key(num)
  unless th
    @stdout.print "No thread ##{num}\n"
    throw :debug_error
  end
  th
end
             
             
               # File debug.rb, line 978
def interrupt
  context(@last_thread).stop_next
end
             
             
               # File debug.rb, line 1036
def make_thread_list
  hash = {}
  for th in Thread::list
    if @thread_list.key? th
      hash[th] = @thread_list[th]
    else
      @max_thread += 1
      hash[th] = @max_thread
    end
  end
  @thread_list = hash
end
             
             
               # File debug.rb, line 954
def resume
  MUTEX.synchronize do
    make_thread_list
    @thread_list.each do |th,|
      next if th == Thread.current
      context(th).clear_suspend
    end
    waiting.each do |th|
      th.run
    end
    waiting.clear
  end
  # Schedule other threads to restart as soon as possible.
  Thread.pass
end
             
             
               # File debug.rb, line 938
def set_last_thread(th)
  @last_thread = th
end
             
             
               # File debug.rb, line 928
def set_trace( arg )
  MUTEX.synchronize do
    make_thread_list
    for th, in @thread_list
      context(th).set_trace arg
    end
  end
  arg
end
             
            Returns the IO used as stdout. Defaults to STDOUT
 
               # File debug.rb, line 897
def stdout
  @stdout
end
             
            Sets the IO used as stdout. Defaults to STDOUT
 
               # File debug.rb, line 902
def stdout=(s)
  @stdout = s
end
             
             
               # File debug.rb, line 942
def suspend
  MUTEX.synchronize do
    make_thread_list
    for th, in @thread_list
      next if th == Thread.current
      context(th).set_suspend
    end
  end
  # Schedule other threads to suspend as soon as possible.
  Thread.pass
end
             
             
               # File debug.rb, line 991
def thread_list(num)
  th = get_thread(num)
  if th == Thread.current
    @stdout.print "+"
  else
    @stdout.print " "
  end
  @stdout.printf "%d ", num
  @stdout.print th.inspect, "\t"
  file = context(th).instance_eval{@file}
  if file
    @stdout.print file,":",context(th).instance_eval{@line}
  end
  @stdout.print "\n"
end
             
            Prints all threads in @thread_list to @stdout. Returns a sorted array of values from the @thread_list hash.
While in the debugger you can list all of the threads with: DEBUGGER__.thread_list_all
(rdb:1) DEBUGGER__.thread_list_all +1 #<Thread:0x007fb2320c03f0 run> debug_me.rb.rb:3 2 #<Thread:0x007fb23218a538 debug_me.rb.rb:3 sleep> 3 #<Thread:0x007fb23218b0f0 debug_me.rb.rb:3 sleep> [1, 2, 3]
Your current thread is indicated by a +
Additionally you can list all threads with th l
(rdb:1) th l +1 #<Thread:0x007f99328c0410 run> debug_me.rb:3 2 #<Thread:0x007f9932938230 debug_me.rb:3 sleep> debug_me.rb:3 3 #<Thread:0x007f9932938e10 debug_me.rb:3 sleep> debug_me.rb:3
See DEBUGGER__ for more usage.
 
               # File debug.rb, line 1030
def thread_list_all
  for th in @thread_list.values.sort
    thread_list(th)
  end
end