Module Debugger
In: cli/ruby-debug/commands/source.rb
cli/ruby-debug/commands/set.rb
cli/ruby-debug/commands/breakpoints.rb
cli/ruby-debug/commands/list.rb
cli/ruby-debug/commands/display.rb
cli/ruby-debug/commands/trace.rb
cli/ruby-debug/commands/frame.rb
cli/ruby-debug/commands/show.rb
cli/ruby-debug/commands/save.rb
cli/ruby-debug/commands/variables.rb
cli/ruby-debug/commands/threads.rb
cli/ruby-debug/commands/irb.rb
cli/ruby-debug/commands/tmate.rb
cli/ruby-debug/commands/kill.rb
cli/ruby-debug/commands/catchpoint.rb
cli/ruby-debug/commands/quit.rb
cli/ruby-debug/commands/method.rb
cli/ruby-debug/commands/finish.rb
cli/ruby-debug/commands/enable.rb
cli/ruby-debug/commands/stepping.rb
cli/ruby-debug/commands/edit.rb
cli/ruby-debug/commands/help.rb
cli/ruby-debug/commands/reload.rb
cli/ruby-debug/commands/eval.rb
cli/ruby-debug/commands/info.rb
cli/ruby-debug/commands/continue.rb
cli/ruby-debug/commands/control.rb
cli/ruby-debug/commands/condition.rb
cli/ruby-debug/helper.rb
cli/ruby-debug/interface.rb
cli/ruby-debug/command.rb
cli/ruby-debug/processor.rb
lib/ruby-debug-base.rb
ext/ruby_debug.c

Debugger is the module name space for ruby-debug.

Methods

Classes and Modules

Module Debugger::ParseFunctions
Class Debugger::AddBreakpoint
Class Debugger::Command
Class Debugger::CommandProcessor
Class Debugger::Context
Class Debugger::ContinueCommand
Class Debugger::ControlCommandProcessor
Class Debugger::DeleteBreakpointCommand
Class Debugger::FinishCommand
Class Debugger::HelpCommand
Class Debugger::IRBCommand
Class Debugger::InfoCommand
Class Debugger::Interface
Class Debugger::KillCommand
Class Debugger::ListCommand
Class Debugger::LocalInterface
Class Debugger::MethodCommand
Class Debugger::MethodSigCommand
Class Debugger::NextCommand
Class Debugger::Processor
Class Debugger::QuitCommand
Class Debugger::ReloadCommand
Class Debugger::RemoteInterface
Class Debugger::ScriptInterface
Class Debugger::SetCommand
Class Debugger::ShowCommand
Class Debugger::SourceCommand
Class Debugger::StepCommand
Class Debugger::VarClassVarCommand
Class Debugger::VarInheritCommand
Class Debugger::VarLocalCommand
Class Debugger::WhereCommand

Constants

RUBY_DEBUG_DIR = File.expand_path(File.dirname(__FILE__)) unless defined?(RUBY_DEBUG_DIR)
DEFAULT_START_SETTINGS = { :init => true, # Set $0 and save ARGV? :post_mortem => false, # post-mortem debugging on uncaught exception? :tracing => nil   Default options to Debugger.start
VERSION = rb_str_new2(DEBUG_VERSION)

Attributes

handler  [RW]  interface modules provide handler object
last_exception  [RW] 
reload_source_on_change  [RW]  if true, checks the modification time of source files and reloads if it was modified

Public Class methods

Adds a new breakpoint. source is a name of a file or a class. pos is a line number or a method name if source is a class name. condition is a string which is evaluated to true when this breakpoint is activated.

[Source]

/*
 *   call-seq:
 *      Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint
 *
 *   Adds a new breakpoint.
 *   <i>source</i> is a name of a file or a class.
 *   <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
 *   <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
 *   is activated.
 */
static VALUE
debug_add_breakpoint(int argc, VALUE *argv, VALUE self)
{
    VALUE result;

    debug_check_started();

    result = create_breakpoint_from_args(argc, argv, ++bkp_count);
    rb_ary_push(rdebug_breakpoints, result);
    return result;
}

Sets catchpoint. Returns the string passed.

[Source]

/*
 *   call-seq:
 *      Debugger.catchpoint(string) -> string
 *
 *   Sets catchpoint. Returns the string passed.
 */
VALUE
rdebug_add_catchpoint(VALUE self, VALUE value)
{
    debug_check_started();

    if (TYPE(value) != T_STRING) {
        rb_raise(rb_eTypeError, "value of a catchpoint must be String");
    }
    rb_hash_aset(rdebug_catchpoints, rb_str_dup(value), INT2FIX(0));
    return value;
}

Returns an Array of Breakpoint objects; all the breakpoints that have been created.

[Source]

/*
 *   call-seq:
 *      Debugger.breakpoints -> Array
 *
 *   Returns an Array of Breakpoint objects; all the breakpoints that
 *   have been created.
 */
static VALUE
debug_breakpoints(VALUE self)
{
    debug_check_started();

    return rdebug_breakpoints;
}

Returns a current catchpoints, which is a hash exception names that will trigger a debugger when raised. The values are the number of times taht catchpoint was hit, initially 0.

[Source]

/*
 *   call-seq:
 *      Debugger.catchpoints -> hash
 *
 *   Returns a current catchpoints, which is a hash exception names that will
 *   trigger a debugger when raised. The values are the number of times taht
 *   catchpoint was hit, initially 0.
 */
VALUE
debug_catchpoints(VALUE self)
{
    debug_check_started();

    return rdebug_catchpoints;
}

Returns an array of all contexts.

[Source]

/*
 *   call-seq:
 *      Debugger.contexts -> array
 *
 *   Returns an array of all contexts.
 */
static VALUE
debug_contexts(VALUE self)
{
    volatile VALUE list;
    volatile VALUE new_list;
    VALUE thread, context;
    threads_table_t *threads_table;
    debug_context_t *debug_context;
    int i;

    debug_check_started();

    new_list = rb_ary_new();
    list = rb_funcall(rb_cThread, idList, 0);
    for(i = 0; i < RARRAY(list)->len; i++)
    {
        thread = rb_ary_entry(list, i);
        thread_context_lookup(thread, &context, NULL);
        rb_ary_push(new_list, context);
    }
    threads_table_clear(rdebug_threads_tbl);
    Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
    for(i = 0; i < RARRAY(new_list)->len; i++)
    {
        context = rb_ary_entry(new_list, i);
        Data_Get_Struct(context, debug_context_t, debug_context);
        st_insert(threads_table->tbl, debug_context->thread_id, context);
    }

    return new_list;
}

Returns current context. Note: Debugger.current_context.thread == Thread.current

[Source]

/*
 *   call-seq:
 *      Debugger.current_context -> context
 *
 *   Returns current context.
 *   <i>Note:</i> Debugger.current_context.thread == Thread.current
 */
static VALUE
debug_current_context(VALUE self)
{
    VALUE thread, context;

    debug_check_started();

    thread = rb_thread_current();
    thread_context_lookup(thread, &context, NULL);

    return context;
}

Register at_exit hook which is escaped from the debugger. FOR INTERNAL USE ONLY.

[Source]

/*
 *   call-seq:
 *      Debugger.debug_at_exit { block } -> proc
 *
 *   Register <tt>at_exit</tt> hook which is escaped from the debugger.
 *   FOR INTERNAL USE ONLY.
 */
static VALUE
debug_at_exit(VALUE self)
{
    VALUE proc;
    if (!rb_block_given_p())
        rb_raise(rb_eArgError, "called without a block");
    proc = rb_block_proc();
    rb_set_end_proc(debug_at_exit_i, proc);
    return proc;
}

Same as Kernel#load but resets current context‘s frames. stop parameter forces the debugger to stop at the first line of code in the file increment_start determines if start_count should be incremented. When

 control threads are used, they have to be set up before loading the
 debugger; so here +increment_start+ will be false.

FOR INTERNAL USE ONLY.

[Source]

/*
 *   call-seq:
 *      Debugger.debug_load(file, stop = false, increment_start = false) -> nil
 *
 *   Same as Kernel#load but resets current context's frames.
 *   +stop+ parameter forces the debugger to stop at the first line of code in the +file+
 *   +increment_start+ determines if start_count should be incremented. When
 *    control threads are used, they have to be set up before loading the
 *    debugger; so here +increment_start+ will be false.    
 *   FOR INTERNAL USE ONLY.
 */
static VALUE
debug_debug_load(int argc, VALUE *argv, VALUE self)
{
    VALUE file, stop, context, increment_start;
    debug_context_t *debug_context;
    int state = 0;
    
    if(rb_scan_args(argc, argv, "12", &file, &stop, &increment_start) == 1) 
    {
        stop = Qfalse;
        increment_start = Qtrue;
    }

    debug_start(self);
    if (Qfalse == increment_start) start_count--;
    
    context = debug_current_context(self);
    Data_Get_Struct(context, debug_context_t, debug_context);
    debug_context->stack_size = 0;
    if(RTEST(stop))
      debug_context->stop_next = 1;
    /* Initializing $0 to the script's path */
    ruby_script(RSTRING(file)->ptr);
    rb_load_protect(file, 0, &state);
    if (0 != state) {
      VALUE errinfo = ruby_errinfo;
      debug_suspend(self);
      reset_stepping_stop_points(debug_context);
      ruby_errinfo = Qnil;
      return errinfo;
    }

    /* We should run all at_exit handler's in order to provide, 
     * for instance, a chance to run all defined test cases */
    rb_exec_end_proc();

    /* We could have issued a Debugger.stop inside the debug
       session. */
    if (start_count > 0) {
      debug_stop(self);
    }

    return Qnil;
}

[Source]

     # File lib/ruby-debug-base.rb, line 147
147:     def handle_post_mortem(exp)
148:       return if !exp || !exp.__debug_context || 
149:         exp.__debug_context.stack_size == 0
150:       Debugger.suspend
151:       orig_tracing = Debugger.tracing, Debugger.current_context.tracing
152:       Debugger.tracing = Debugger.current_context.tracing = false
153:       Debugger.last_exception = exp
154:       handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line)
155:     ensure
156:       Debugger.tracing, Debugger.current_context.tracing = orig_tracing
157:       Debugger.resume
158:     end

[Source]

     # File cli/ruby-debug/commands/show.rb, line 222
222:       def help(args)
223:         if args[1] 
224:           s = args[1]
225:           subcmd = Subcommands.find do |try_subcmd| 
226:             (s.size >= try_subcmd.min) and
227:               (try_subcmd.name[0..s.size-1] == s)
228:           end
229:           if subcmd
230:             str = subcmd.short_help + '.'
231:             str += "\n" + subcmd.long_help if subcmd.long_help
232:             return str
233:           else
234:             return "Invalid 'show' subcommand '#{args[1]}'."
235:           end
236:         end
237:         s = "
238:           Generic command for showing things about the debugger.
239: 
240:           -- 
241:           List of show subcommands:
242:           --  
243:         "
244:         for subcmd in Subcommands do
245:           s += "show #{subcmd.name} -- #{subcmd.short_help}\n"
246:         end
247:         return s
248:       end

[Source]

     # File cli/ruby-debug/commands/set.rb, line 206
206:       def help(args)
207:         if args[1] 
208:           s = args[1]
209:           subcmd = Subcommands.find do |try_subcmd| 
210:             (s.size >= try_subcmd.min) and
211:               (try_subcmd.name[0..s.size-1] == s)
212:           end
213:           if subcmd
214:             str = subcmd.short_help + '.'
215:             str += "\n" + subcmd.long_help if subcmd.long_help
216:             return str
217:           else
218:             return "Invalid 'set' subcommand '#{args[1]}'."
219:           end
220:         end
221:         s = %{
222:           Modifies parts of the ruby-debug environment. Boolean values take
223:           on, off, 1 or 0.
224:           You can see these environment settings with the \"show\" command.
225: 
226:           -- 
227:           List of set subcommands:
228:           --  
229:         }
230:         for subcmd in Subcommands do
231:           s += "set #{subcmd.name} -- #{subcmd.short_help}\n"
232:         end
233:         return s
234:       end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 431
431:       def help(args)
432:         if args[1] 
433:           s = args[1]
434:           subcmd = Subcommands.find do |try_subcmd| 
435:             (s.size >= try_subcmd.min) and
436:               (try_subcmd.name[0..s.size-1] == s)
437:           end
438:           if subcmd
439:             str = subcmd.short_help + '.'
440:             if 'file' == subcmd.name and args[2]
441:               s = args[2]
442:               subsubcmd = InfoFileSubcommands.find do |try_subcmd|
443:                 (s.size >= try_subcmd.min) and
444:                   (try_subcmd.name[0..s.size-1] == s)
445:               end
446:               if subsubcmd
447:                 str += "\n" + subsubcmd.short_help + '.'
448:               else
449:                 str += "\nInvalid file attribute #{args[2]}."
450:               end
451:             else
452:               str += "\n" + subcmd.long_help if subcmd.long_help
453:             end
454:             return str
455:           else
456:             return "Invalid 'info' subcommand '#{args[1]}'."
457:           end
458:         end
459:         s = %{
460:           Generic command for showing things about the program being debugged.
461:           -- 
462:           List of info subcommands:
463:           --  
464:         }
465:         for subcmd in Subcommands do
466:           s += "info #{subcmd.name} -- #{subcmd.short_help}\n"
467:         end
468:         return s
469:       end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 427
427:       def help_command
428:         'info'
429:       end

[Source]

     # File cli/ruby-debug/commands/set.rb, line 202
202:       def help_command
203:         "set"
204:       end

[Source]

     # File cli/ruby-debug/commands/show.rb, line 218
218:       def help_command
219:         "show"
220:       end

Interrupts the current thread

[Source]

    # File lib/ruby-debug-base.rb, line 77
77:     def interrupt
78:       current_context.interrupt
79:     end

Interrupts the last debugged thread

[Source]

    # File lib/ruby-debug-base.rb, line 84
84:     def interrupt_last
85:       if context = last_context
86:         return nil unless context.thread.alive?
87:         context.interrupt
88:       end
89:       context
90:     end

Setting to true will make the debugger create frame bindings.

[Source]

/*
 *   call-seq:
 *      Debugger.keep_frame_binding = bool
 *
 *   Setting to +true+ will make the debugger create frame bindings.
 */
static VALUE
debug_set_keep_frame_binding(VALUE self, VALUE value)
{
    keep_frame_binding = RTEST(value) ? Qtrue : Qfalse;
    return value;
}

Returns true if the debugger will collect frame bindings.

[Source]

/*
 *   call-seq:
 *      Debugger.keep_frame_binding? -> bool
 *
 *   Returns +true+ if the debugger will collect frame bindings.
 */
static VALUE
debug_keep_frame_binding(VALUE self)
{
    return keep_frame_binding;
}

Returns last debugged context.

[Source]

/*
 *   call-seq:
 *      Debugger.last_interrupted -> context
 *
 *   Returns last debugged context.
 */
static VALUE
debug_last_interrupted(VALUE self)
{
    VALUE result = Qnil;
    threads_table_t *threads_table;

    debug_check_started();

    Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);

    st_foreach(threads_table->tbl, find_last_context_func, (st_data_t)&result);
    return result;
}

Activates the post-mortem mode. There are two ways of using it:

Global post-mortem mode

By calling Debugger.post_mortem method without a block, you install at_exit hook that intercepts any unhandled by your script exceptions and enables post-mortem mode.

Local post-mortem mode

If you know that a particular block of code raises an exception you can enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g.

  def offender
     raise 'error'
  end
  Debugger.post_mortem do
     ...
     offender
     ...
  end

[Source]

     # File lib/ruby-debug-base.rb, line 126
126:     def post_mortem
127:       if block_given?
128:         old_post_mortem = self.post_mortem?
129:         begin
130:           self.post_mortem = true
131:           yield
132:         rescue Exception => exp
133:           handle_post_mortem(exp)
134:           raise
135:         ensure
136:           self.post_mortem = old_post_mortem
137:         end
138:       else
139:         return if post_mortem?
140:         self.post_mortem = true
141:         debug_at_exit do
142:           handle_post_mortem($!) if $! && post_mortem?
143:         end
144:       end
145:     end

Sets post-moterm flag. FOR INTERNAL USE ONLY.

[Source]

/*
 *   call-seq:
 *      Debugger.post_mortem = bool
 *
 *   Sets post-moterm flag.
 *   FOR INTERNAL USE ONLY.
 */
static VALUE
debug_set_post_mortem(VALUE self, VALUE value)
{
    debug_check_started();

    post_mortem = RTEST(value) ? Qtrue : Qfalse;
    return value;
}

Returns true if post-moterm debugging is enabled.

[Source]

/*
 *   call-seq:
 *      Debugger.post_mortem? -> bool
 *
 *   Returns +true+ if post-moterm debugging is enabled.
 */
static VALUE
debug_post_mortem(VALUE self)
{
    return post_mortem;
}

Removes breakpoint by its id. id is an identificator of a breakpoint.

[Source]

/*
 *   call-seq:
 *      Debugger.remove_breakpoint(id) -> breakpoint
 *
 *   Removes breakpoint by its id.
 *   <i>id</i> is an identificator of a breakpoint.
 */
VALUE
rdebug_remove_breakpoint(VALUE self, VALUE id_value)
{
    int i;
    int id;
    VALUE breakpoint;
    debug_breakpoint_t *debug_breakpoint;

    id = FIX2INT(id_value);

    for( i = 0; i < RARRAY(rdebug_breakpoints)->len; i += 1 )
    {
        breakpoint = rb_ary_entry(rdebug_breakpoints, i);
        Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
        if(debug_breakpoint->id == id)
        {
            rb_ary_delete_at(rdebug_breakpoints, i);
            return breakpoint;
        }
    }
    return Qnil;
}

Resumes all contexts.

[Source]

/*
 *   call-seq:
 *      Debugger.resume -> Debugger
 *
 *   Resumes all contexts.
 */
static VALUE
debug_resume(VALUE self)
{
    VALUE current, context;
    VALUE saved_crit;
    VALUE context_list;
    debug_context_t *debug_context;
    int i;

    debug_check_started();

    saved_crit = rb_thread_critical;
    rb_thread_critical = Qtrue;
    context_list = debug_contexts(self);

    thread_context_lookup(rb_thread_current(), &current, NULL);
    for(i = 0; i < RARRAY(context_list)->len; i++)
    {
        context = rb_ary_entry(context_list, i);
        if(current == context)
            continue;
        Data_Get_Struct(context, debug_context_t, debug_context);
        context_resume_0(debug_context);
    }
    rb_thread_critical = saved_crit;

    rb_thread_schedule();

    return self;
}

Returns setting object. Use Debugger.settings[] and Debugger.settings[]= methods to query and set debugger settings. These settings are available:

  • :autolist - automatically calls ‘list’ command on breakpoint
  • :autoeval - evaluates input in the current binding if it‘s not recognized as a debugger command
  • :autoirb - automatically calls ‘irb’ command on breakpoint
  • :stack_trace_on_error - shows full stack trace if eval command results with an exception
  • :frame_full_path - displays full paths when showing frame stack
  • :frame_class_names - displays method‘s class name when showing frame stack
  • :reload_source_on_change - makes ‘list’ command to always display up-to-date source code
  • :force_stepping - stepping command asways move to the new line

[Source]

     # File cli/ruby-debug/command.rb, line 264
264:   def self.settings
265:     Command.settings
266:   end

The code inside of the block is escaped from the debugger.

[Source]

/*
 *   call-seq:
 *      Debugger.skip { block } -> obj or nil
 *
 *   The code inside of the block is escaped from the debugger.
 */
static VALUE
debug_skip(VALUE self)
{
    if (!rb_block_given_p()) {
        rb_raise(rb_eArgError, "called without a block");
    }
    if(!IS_STARTED)
        return rb_yield(Qnil);
    set_current_skipped_status(Qtrue);
    return rb_ensure(rb_yield, Qnil, set_current_skipped_status, Qfalse);
}

[Source]

    # File lib/ruby-debug-base.rb, line 92
92:     def source_reload
93:       LineCache::clear_file_cache
94:     end

This method is internal and activates the debugger. Use Debugger.start (from lib/ruby-debug-base.rb) instead.

The return value is the value of !Debugger.started? before issuing the start; That is, true is returned, unless debugger was previously started.

If a block is given, it starts debugger and yields to block. When the block is finished executing it stops the debugger with Debugger.stop method. Inside the block you will probably want to have a call to Debugger.debugger. For example:

  Debugger.start{debugger; foo}  # Stop inside of foo

Also, ruby-debug only allows one invocation of debugger at a time; nested Debugger.start‘s have no effect and you can‘t use this inside the debugger itself.

Note that if you want to completely remove the debugger hook, you must call Debugger.stop as many times as you called Debugger.start method.

[Source]

/*
 *   call-seq:
 *      Debugger.start_ -> bool
 *      Debugger.start_ { ... } -> bool
 *
 *   This method is internal and activates the debugger. Use
 *   Debugger.start (from <tt>lib/ruby-debug-base.rb</tt>) instead.
 *
 *   The return value is the value of !Debugger.started? <i>before</i>
 *   issuing the +start+; That is, +true+ is returned, unless debugger
 *   was previously started.

 *   If a block is given, it starts debugger and yields to block. When
 *   the block is finished executing it stops the debugger with
 *   Debugger.stop method. Inside the block you will probably want to
 *   have a call to Debugger.debugger. For example:
 *     Debugger.start{debugger; foo}  # Stop inside of foo
 * 
 *   Also, ruby-debug only allows
 *   one invocation of debugger at a time; nested Debugger.start's
 *   have no effect and you can't use this inside the debugger itself.
 *
 *   <i>Note that if you want to completely remove the debugger hook,
 *   you must call Debugger.stop as many times as you called
 *   Debugger.start method.</i>
 */
static VALUE
debug_start(VALUE self)
{
    VALUE result;
    start_count++;

    if(IS_STARTED)
        result = Qfalse;
    else
    {
        locker             = Qnil;
        rdebug_breakpoints = rb_ary_new();
        rdebug_catchpoints = rb_hash_new();
        rdebug_threads_tbl = threads_table_create();

        rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
        result = Qtrue;
    }

    if(rb_block_given_p()) 
      rb_ensure(rb_yield, self, debug_stop_i, self);

    return result;
}

Returns true the debugger is started.

[Source]

/*
 *   call-seq:
 *      Debugger.started? -> bool
 *
 *   Returns +true+ the debugger is started.
 */
static VALUE
debug_is_started(VALUE self)
{
    return IS_STARTED ? Qtrue : Qfalse;
}

This method disables the debugger. It returns true if the debugger is disabled, otherwise it returns false.

Note that if you want to complete remove the debugger hook, you must call Debugger.stop as many times as you called Debugger.start method.

[Source]

/*
 *   call-seq:
 *      Debugger.stop -> bool
 *
 *   This method disables the debugger. It returns +true+ if the debugger is disabled,
 *   otherwise it returns +false+.
 *
 *   <i>Note that if you want to complete remove the debugger hook,
 *   you must call Debugger.stop as many times as you called
 *   Debugger.start method.</i>
 */
static VALUE
debug_stop(VALUE self)
{
    debug_check_started();

    start_count--;
    if(start_count)
        return Qfalse;

    rb_remove_event_hook(debug_event_hook);

    locker             = Qnil;
    rdebug_breakpoints = Qnil;
    rdebug_threads_tbl = Qnil;

    return Qtrue;
}

Suspends all contexts.

[Source]

/*
 *   call-seq:
 *      Debugger.suspend -> Debugger
 *
 *   Suspends all contexts.
 */
static VALUE
debug_suspend(VALUE self)
{
    VALUE current, context;
    VALUE saved_crit;
    VALUE context_list;
    debug_context_t *debug_context;
    int i;

    debug_check_started();

    saved_crit = rb_thread_critical;
    rb_thread_critical = Qtrue;
    context_list = debug_contexts(self);
    thread_context_lookup(rb_thread_current(), &current, NULL);

    for(i = 0; i < RARRAY(context_list)->len; i++)
    {
        context = rb_ary_entry(context_list, i);
        if(current == context)
            continue;
        Data_Get_Struct(context, debug_context_t, debug_context);
        context_suspend_0(debug_context);
    }
    rb_thread_critical = saved_crit;

    if(rb_thread_critical == Qfalse)
        rb_thread_schedule();

    return self;
}

Returns context of the thread passed as an argument.

[Source]

/*
 *   call-seq:
 *      Debugger.thread_context(thread) -> context
 *
 *   Returns context of the thread passed as an argument.
 */
static VALUE
debug_thread_context(VALUE self, VALUE thread)
{
    VALUE context;

    debug_check_started();
    thread_context_lookup(thread, &context, NULL);
    return context;
}

Returns true if the global tracing is activated.

[Source]

/*
 *   call-seq:
 *      Debugger.tracing -> bool
 *
 *   Returns +true+ if the global tracing is activated.
 */
static VALUE
debug_tracing(VALUE self)
{
    return tracing;
}

Sets the global tracing flag.

[Source]

/*
 *   call-seq:
 *      Debugger.tracing = bool
 *
 *   Sets the global tracing flag.
 */
static VALUE
debug_set_tracing(VALUE self, VALUE value)
{
    tracing = RTEST(value) ? Qtrue : Qfalse;
    return value;
}

Setting to true will make the debugger save argument info on calls.

[Source]

/*
 *   call-seq:
 *      Debugger.track_frame_args = bool
 *
 *   Setting to +true+ will make the debugger save argument info on calls.
 */
static VALUE
debug_set_track_frame_args(VALUE self, VALUE value)
{
    track_frame_args = RTEST(value) ? Qtrue : Qfalse;
    return value;
}

Returns true if the debugger track frame argument values on calls.

[Source]

/*
 *   call-seq:
 *      Debugger.track_fame_args? -> bool
 *
 *   Returns +true+ if the debugger track frame argument values on calls.
 */
static VALUE
debug_track_frame_args(VALUE self)
{
    return track_frame_args;
}

Public Instance methods

[Source]

     # File cli/ruby-debug/commands/info.rb, line 93
 93:     def execute
 94:       if !@match[1] || @match[1].empty?
 95:         errmsg "\"info\" must be followed by the name of an info command:\n"
 96:         print "List of info subcommands:\n\n"
 97:         for subcmd in Subcommands do
 98:           print "info #{subcmd.name} -- #{subcmd.short_help}\n"
 99:         end
100:       else
101:         args = @match[1].split(/[ \t]+/)
102:         param = args.shift
103:         subcmd = find(Subcommands, param)
104:         if subcmd
105:           send("info_#{subcmd.name}", *args)
106:         else
107:           errmsg "Unknown info command #{param}\n"
108:         end
109:       end
110:     end

[Source]

     # File cli/ruby-debug/commands/set.rb, line 63
 63:     def execute
 64:       if not @match[1]
 65:         print "\"set\" must be followed by the name of an set command:\n"
 66:         print "List of set subcommands:\n\n"
 67:         for subcmd in Subcommands do
 68:           print "set #{subcmd.name} -- #{subcmd.short_help}\n"
 69:         end
 70:       else
 71:         args = @match[1].split(/[ \t]+/)
 72:         subcmd = args.shift
 73:         subcmd.downcase!
 74:         if subcmd =~ /^no/i
 75:           set_on = false
 76:           subcmd = subcmd[2..-1]
 77:         else
 78:           set_on = true
 79:         end
 80:         for try_subcmd in Subcommands do
 81:           if (subcmd.size >= try_subcmd.min) and
 82:               (try_subcmd.name[0..subcmd.size-1] == subcmd)
 83:             begin
 84:               if try_subcmd.is_bool
 85:                 if args.size > 0 
 86:                   set_on = get_onoff(args[0]) 
 87:                 end
 88:               end
 89:               case try_subcmd.name
 90:               when /^annotate$/
 91:                 level = get_int(args[0], "Set annotate", 0, 3, 0)
 92:                 if level
 93:                   Debugger.annotate = level
 94:                 else
 95:                   return
 96:                 end
 97:                 if defined?(Debugger::RDEBUG_SCRIPT)
 98:                   # rdebug was called initially. 1st arg is script name.
 99:                   Command.settings[:argv][1..-1] = args
100:                 else
101:                   # rdebug wasn't called initially. 1st arg is not script name.
102:                   Command.settings[:argv] = args
103:                 end
104:               when /^args$/
105:                 Command.settings[:argv][1..-1] = args
106:               when /^autolist$/
107:                 Command.settings[:autolist] = (set_on ? 1 : 0)
108:               when /^autoeval$/
109:                 Command.settings[:autoeval] = set_on
110:               when /^basename$/
111:                 Command.settings[:basename] = set_on
112:               when /^callstyle$/
113:                 if args[0]
114:                   arg = args[0].downcase.to_sym
115:                   case arg
116:                   when :short, :last, :tracked
117:                     Command.settings[:callstyle] = arg
118:                     Debugger.track_frame_args = arg == :tracked ? true : false
119:                     print "%s\n" % show_setting(try_subcmd.name)
120:                     return
121:                   end
122:                 end
123:                 print "Invalid call style #{arg}. Should be one of: " +
124:                   "'short', 'last', or 'tracked'.\n"
125:               when /^trace$/
126:                 Command.settings[:stack_trace_on_error] = set_on
127:               when /^fullpath$/
128:                 Command.settings[:full_path] = set_on
129:               when /^autoreload$/
130:                 Command.settings[:reload_source_on_change] = set_on
131:               when /^autoirb$/
132:                 Command.settings[:autoirb] = (set_on ? 1 : 0)
133:               when /^debuggertesting$/
134:                 Command.settings[:debuggertesting] = set_on
135:                 if set_on
136:                   Command.settings[:basename] = true
137:                 end
138:               when /^forcestep$/
139:                 self.class.settings[:force_stepping] = set_on
140:               when /^history$/
141:                 if 2 == args.size
142:                   interface = @state.interface
143:                   case args[0]
144:                   when /^save$/
145:                     interface.history_save = get_onoff(args[1])
146:                   when /^size$/
147:                     interface.history_length = get_int(args[1],
148:                                                        "Set history size")
149:                   else
150:                     print "Invalid history parameter #{args[0]}. Should be 'save' or 'size'.\n" 
151:                   end
152:                 else
153:                   print "Need two parameters for 'set history'; got #{args.size}.\n" 
154:                   return
155:                 end
156:               when /^keep-frame-bindings$/
157:                 Debugger.keep_frame_binding = set_on
158:               when /^linetrace\+$/
159:                 self.class.settings[:tracing_plus] = set_on
160:               when /^linetrace$/
161:                 Debugger.tracing = set_on
162:               when /^listsize$/
163:                 listsize = get_int(args[0], "Set listsize", 1, nil, 10)
164:                 if listsize
165:                   self.class.settings[:listsize] = listsize
166:                 else
167:                   return
168:                 end
169: #               when /^post-mortem$/
170: #                 unless Debugger.post_mortem? == set_on
171: #                   if set_on
172: #                     Debugger.post_mortem
173: #                   else
174: #                     errmsg "Can't turn off post-mortem once it is on.\n"
175: #                     return
176: #                   end
177: #                 end
178:               when /^width$/
179:                 width = get_int(args[0], "Set width", 10, nil, 80)
180:                 if width
181:                   self.class.settings[:width] = width
182:                   ENV['COLUMNS'] = width.to_s
183:                 else
184:                   return
185:                 end
186:               else
187:                 print "Unknown setting #{@match[1]}.\n"
188:                 return
189:               end
190:               print "%s\n" % show_setting(try_subcmd.name)
191:               return
192:             rescue RuntimeError
193:               return
194:             end
195:           end
196:         end
197:         print "Unknown set command #{subcmd}\n"
198:       end
199:     end

[Source]

     # File cli/ruby-debug/commands/show.rb, line 198
198:     def execute
199:       if not @match[1]
200:         print "\"show\" must be followed by the name of an show command:\n"
201:         print "List of show subcommands:\n\n"
202:         for subcmd in Subcommands do
203:           print "show #{subcmd.name} -- #{subcmd.short_help}\n"
204:         end
205:       else
206:         args = @match[1].split(/[ \t]+/)
207:         param = args.shift
208:         subcmd = find(Subcommands, param)
209:         if subcmd
210:           print "%s\n" % show_setting(subcmd.name)
211:         else
212:           print "Unknown show command #{param}\n"
213:         end
214:       end
215:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 112
112:     def info_args(*args)
113:       unless @state.context
114:         print "No frame selected.\n"
115:         return 
116:       end
117:       locals = @state.context.frame_locals(@state.frame_pos)
118:       args = @state.context.frame_args(@state.frame_pos)
119:       args.each do |name|
120:         s = "#{name} = #{locals[name].inspect}"
121:         if s.size > self.class.settings[:width]
122:           s[self.class.settings[:width]-3 .. -1] = "..."
123:         end
124:         print "#{s}\n"
125:       end
126:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 128
128:     def info_breakpoints(*args)
129:       unless @state.context
130:         print "info breakpoints not available here.\n"
131:         return 
132:       end
133:       unless Debugger.breakpoints.empty?
134:         brkpts = Debugger.breakpoints.sort_by{|b| b.id}
135:         unless args.empty?
136:           a = args.map{|a| a.to_i}
137:           brkpts = brkpts.select{|b| a.member?(b.id)}
138:           if brkpts.empty?
139:             errmsg "No breakpoints found among list given.\n"
140:             return
141:           end
142:         end
143:         print "Num Enb What\n"
144:         brkpts.each do |b|
145:           fname = Command.settings[:basename] ? 
146:              File.basename(b.source) : b.source
147:             
148:           if b.expr.nil?
149:             print "%3d %s   at %s:%s\n", 
150:             b.id, (b.enabled? ? 'y' : 'n'), fname, b.pos
151:           else
152:             print "%3d %s   at %s:%s if %s\n", 
153:             b.id, (b.enabled? ? 'y' : 'n'), fname, b.pos, b.expr
154:           end
155:           hits = b.hit_count
156:           if hits > 0
157:             s = (hits > 1) ? 's' : ''
158:             print "\tbreakpoint already hit #{hits} time#{s}\n"
159:           end
160:         end
161:       else
162:         print "No breakpoints.\n"
163:       end
164:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 166
166:     def info_display(*args)
167:       unless @state.context
168:         print "info display not available here.\n"
169:         return 
170:       end
171:       if @state.display.find{|d| d[0]}
172:         print "Auto-display expressions now in effect:\n"
173:         print "Num Enb Expression\n"
174:         n = 1
175:         for d in @state.display
176:           print "%3d: %s  %s\n", n, (d[0] ? 'y' : 'n'), d[1] if
177:             d[0] != nil
178:           n += 1
179:         end
180:       else
181:         print "There are no auto-display expressions now.\n"
182:       end
183:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 185
185:     def info_file(*args)
186:       unless args[0] 
187:         info_files
188:         return
189:       end
190:       file = args[0]
191:       param =  args[1]
192:       
193:       param = 'basic' unless param
194:       subcmd = find(InfoFileSubcommands, param)
195:       unless subcmd
196:         errmsg "Invalid parameter #{param}\n"
197:         return
198:       end
199:       
200:       unless LineCache::cached?(file)
201:         unless LineCache::cached_script?(file)
202:           print "File #{file} is not cached\n"
203:           return
204:         end
205:         LineCache::cache(file, Command.settings[:reload_source_on_change])
206:       end
207:       
208:       print "File %s", file
209:       path = LineCache.path(file)
210:       if %w(all basic path).member?(subcmd.name) and path != file
211:         print " - %s\n", path 
212:       else
213:         print "\n"
214:       end
215: 
216:       if %w(all basic lines).member?(subcmd.name)
217:         lines = LineCache.size(file)
218:         print "\t %d lines\n", lines if lines
219:       end
220: 
221:       if %w(all breakpoints).member?(subcmd.name)
222:         breakpoints = LineCache.trace_line_numbers(file)
223:         if breakpoints
224:           print "\tbreakpoint line numbers:\n" 
225:           print columnize(breakpoints.to_a.sort, self.class.settings[:width])
226:         end
227:       end
228: 
229:       if %w(all mtime).member?(subcmd.name)
230:         stat = LineCache.stat(file)
231:         print "\t%s\n", stat.mtime if stat
232:       end
233:       if %w(all sha1).member?(subcmd.name)
234:         print "\t%s\n", LineCache.sha1(file)
235:       end
236:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 238
238:     def info_files(*args)
239:       files = LineCache::cached_files
240:       files += SCRIPT_LINES__.keys unless 'stat' == args[0] 
241:       files.uniq.sort.each do |file|
242:         stat = LineCache::stat(file)
243:         path = LineCache::path(file)
244:         print "File %s", file
245:         if path and path != file
246:           print " - %s\n", path 
247:         else
248:           print "\n"
249:         end
250:         print "\t%s\n", stat.mtime if stat
251:       end
252:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 388
388:     def info_global_variables(*args)
389:       unless @state.context
390:         errmsg "info global_variables not available here.\n"
391:         return 
392:       end
393:       var_list(global_variables)
394:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 254
254:     def info_instance_variables(*args)
255:       unless @state.context
256:         print "info instance_variables not available here.\n"
257:         return 
258:       end
259:       obj = debug_eval('self')
260:       var_list(obj.instance_variables)
261:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 263
263:     def info_line(*args)
264:       unless @state.context
265:         errmsg "info line not available here.\n"
266:         return 
267:       end
268:       print "Line %d of \"%s\"\n",  @state.line, @state.file
269:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 271
271:     def info_locals(*args)
272:       unless @state.context
273:         errmsg "info line not available here.\n"
274:         return 
275:       end
276:       locals = @state.context.frame_locals(@state.frame_pos)
277:       locals.keys.sort.each do |name|
278:         ### FIXME: make a common routine
279:         begin
280:           s = "#{name} = #{locals[name].inspect}"
281:         rescue
282:           begin
283:           s = "#{name} = #{locals[name].to_s}"
284:           rescue
285:             s = "*Error in evaluation*"
286:           end
287:         end  
288:         if s.size > self.class.settings[:width]
289:           s[self.class.settings[:width]-3 .. -1] = "..."
290:         end
291:         print "#{s}\n"
292:       end
293:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 295
295:     def info_program(*args)
296:       if not @state.context
297:         print "The program being debugged is not being run.\n"
298:         return
299:       elsif @state.context.dead? 
300:         print "The program crashed.\n"
301:         if Debugger.last_exception
302:           print("Exception: #{Debugger.last_exception.inspect}\n")
303:         end
304:         return
305:       end
306:       
307:       print "Program stopped. "
308:       case @state.context.stop_reason
309:       when :step
310:         print "It stopped after stepping, next'ing or initial start.\n"
311:       when :breakpoint
312:         print("It stopped at a breakpoint.\n")
313:       when :catchpoint
314:         print("It stopped at a catchpoint.\n")
315:       when :catchpoint
316:         print("It stopped at a catchpoint.\n")
317:       else
318:         print "unknown reason: %s\n" % @state.context.stop_reason.to_s
319:       end
320:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 322
322:     def info_stack(*args)
323:       if not @state.context
324:         errmsg "info stack not available here.\n"
325:         return
326:       end
327:       (0...@state.context.stack_size).each do |idx|
328:         if idx == @state.frame_pos
329:           print "--> "
330:         else
331:           print "    "
332:         end
333:         print_frame(idx)
334:       end
335:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 370
370:     def info_thread(*args)
371:       unless args[0]
372:         info_threads(args[0])
373:         return
374:       end
375:       ok, verbose = info_thread_preamble(args[1])
376:       return unless ok
377:       c = parse_thread_num("info thread" , args[0])
378:       return unless c
379:       display_context(c, !verbose)
380:       if verbose and not c.ignored?
381:         (0...c.stack_size).each do |idx|
382:           print "\t"
383:           print_frame(idx, false, c) 
384:         end
385:       end
386:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 356
356:     def info_threads(*args)
357:       ok, verbose = info_thread_preamble(args[0])
358:       return unless ok
359:       threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c|
360:         display_context(c, !verbose)
361:         if verbose and not c.ignored?
362:           (0...c.stack_size).each do |idx|
363:             print "\t"
364:             print_frame(idx, false, c)
365:           end
366:         end
367:       end
368:     end

[Source]

     # File cli/ruby-debug/commands/info.rb, line 396
396:     def info_variables(*args)
397:       if not @state.context
398:         errmsg "info variables not available here.\n"
399:         return
400:       end
401:       obj = debug_eval('self')
402:       locals = @state.context.frame_locals(@state.frame_pos)
403:       locals['self'] = @state.context.frame_self(@state.frame_pos)
404:       locals.keys.sort.each do |name|
405:         next if name =~ /^__dbg_/ # skip debugger pollution
406:         ### FIXME: make a common routine
407:         begin
408:           s = "#{name} = #{locals[name].inspect}"
409:         rescue
410:           begin
411:             s = "#{name} = #{locals[name].to_s}"
412:           rescue
413:             s = "#{name} = *Error in evaluation*"
414:           end
415:         end
416:         if s.size > self.class.settings[:width]
417:           s[self.class.settings[:width]-3 .. -1] = "..."
418:         end
419:         s.gsub!('%', '%%')  # protect against printf format strings
420:         print "#{s}\n"
421:       end
422:       var_list(obj.instance_variables, obj.instance_eval{binding()})
423:       var_class_self
424:     end

[Source]

   # File cli/ruby-debug/helper.rb, line 3
3:   def inside_emacs?
4:     ENV['EMACS'] || ENV['INSIDE_EMACS']
5:   end

[Source]

    # File cli/ruby-debug/commands/set.rb, line 59
59:     def regexp
60:       /^set (?: \s+ (.*) )?$/ix
61:     end

[Source]

    # File cli/ruby-debug/commands/info.rb, line 89
89:     def regexp
90:       /^\s* i(?:nfo)? (?:\s+(.*))?$/ix
91:     end

[Source]

     # File cli/ruby-debug/commands/show.rb, line 194
194:     def regexp
195:       /^show (?: \s+ (.+) )?$/xi
196:     end

Debugger.start(options) -> bool Debugger.start(options) { … } -> obj

If it‘s called without a block it returns true, unless debugger was already started. If a block is given, it starts debugger and yields to block. When the block is finished executing it stops the debugger with Debugger.stop method.

If a block is given, it starts debugger and yields to block. When the block is finished executing it stops the debugger with Debugger.stop method. Inside the block you will probably want to have a call to Debugger.debugger. For example:

    Debugger.start{debugger; foo}  # Stop inside of foo

Also, ruby-debug only allows one invocation of debugger at a time; nested Debugger.start‘s have no effect and you can‘t use this inside the debugger itself.

Note that if you want to stop debugger, you must call Debugger.stop as many time as you called Debugger.start method.

options is a hash used to set various debugging options. Set :init true if you want to save ARGV and some variables which make a debugger restart possible. Only the first time :init is set true will values get set. Since ARGV is saved, you should make sure it hasn‘t been changed before the (first) call. Set :post_mortem true if you want to enter post-mortem debugging on an uncaught exception. Once post-mortem debugging is set, it can‘t be unset.

[Source]

     # File lib/ruby-debug-base.rb, line 199
199:   def start(options={}, &block)
200:     options = Debugger::DEFAULT_START_SETTINGS.merge(options)
201:     if options[:init]
202:       Debugger.const_set('ARGV', ARGV.clone) unless 
203:         defined? Debugger::ARGV
204:       Debugger.const_set('PROG_SCRIPT', $0) unless 
205:         defined? Debugger::PROG_SCRIPT
206:       Debugger.const_set('INITIAL_DIR', Dir.pwd) unless 
207:         defined? Debugger::INITIAL_DIR
208:     end
209:     Debugger.tracing = options[:tracing] unless options[:tracing].nil?
210:     retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block) 
211:     if options[:post_mortem]
212:       post_mortem
213:     end
214:     return retval
215:   end

[Validate]