class DEBUGGER__ - RDoc Documentation

# class DEBUGGER__

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"

## Getting help¶ ↑

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

## Usage¶ ↑

The following is a list of common functionalities that the debugger provides.

### Navigating through your code¶ ↑

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.

### Inspecting variables¶ ↑

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

### Going beyond basics¶ ↑

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`.

## Staying out of trouble¶ ↑

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.

### Constants

CONTINUATIONS_SUPPORTED

### Public Class Methods

break_points() click to toggle source

Returns the list of break points where execution will be stopped.

See `DEBUGGER__` for more usage

    # File lib/debug.rb, line 928
    def break_points
      @break_points
    end

context(thread=Thread.current) click to toggle source

    # File lib/debug.rb, line 982
    def context(thread=Thread.current)
      c = thread[:__debugger_data__]
      unless c
        thread[:__debugger_data__] = c = Context.new
      end
      c
    end

debug_thread_info(input, binding) click to toggle source

    # File lib/debug.rb, line 1061
    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

display() click to toggle source

Returns the display expression list

See `DEBUGGER__` for more usage

    # File lib/debug.rb, line 921
    def display
      @display
    end

get_thread(num) click to toggle source

    # File lib/debug.rb, line 994
    def get_thread(num)
      th = @thread_list.key(num)
      unless th
        @stdout.print "No thread ##{num}\n"
        throw :debug_error
      end
      th
    end

interrupt() click to toggle source

    # File lib/debug.rb, line 990
    def interrupt
      context(@last_thread).stop_next
    end

make_thread_list() click to toggle source

    # File lib/debug.rb, line 1048
    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

resume() click to toggle source

    # File lib/debug.rb, line 966
    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

set_last_thread(th) click to toggle source

    # File lib/debug.rb, line 950
    def set_last_thread(th)
      @last_thread = th
    end

set_trace( arg ) click to toggle source

    # File lib/debug.rb, line 940
    def set_trace( arg )
      MUTEX.synchronize do
        make_thread_list
        for th, in @thread_list
          context(th).set_trace arg
        end
      end
      arg
    end

stdout() click to toggle source

Returns the `IO` used as stdout. Defaults to STDOUT

    # File lib/debug.rb, line 909
    def stdout
      @stdout
    end

stdout=(s) click to toggle source

Sets the `IO` used as stdout. Defaults to STDOUT

    # File lib/debug.rb, line 914
    def stdout=(s)
      @stdout = s
    end

suspend() click to toggle source

    # File lib/debug.rb, line 954
    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

thread_list(num) click to toggle source

    # File lib/debug.rb, line 1003
    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

thread_list_all() click to toggle source

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 lib/debug.rb, line 1042
    def thread_list_all
      for th in @thread_list.values.sort
        thread_list(th)
      end
    end

waiting() click to toggle source

Returns the list of waiting threads.

When stepping through the traces of a function, thread gets suspended, to be resumed later.

    # File lib/debug.rb, line 936
    def waiting
      @waiting
    end