# module Byebug

## Summary¶ ↑

This is a singleton class allows controlling byebug. Use it to start/stop byebug, set/remove breakpoints, etc.

Main Container for all of Byebug's code

Main debugger's container module. Everything is defined under this module

Namespace for all of byebug's code

Remote debugging functionality.

Reopen main module to define the library version

### Constants

PORT

  Port number used for remote debugging

VERSION

### Attributes

wait_connection[RW]

If in remote mode, wait for the remote connection

displays[RW]

Debugger's display expressions

init_file[RW]

Configuration file used for startup commands. Default value is .byebugrc

mode[RW]

Running mode of the debugger. Can be either:

- :attached => Attached to a running program through the `byebug` method.

- :standalone => Started through `byebug` script.

- :off => Ignoring any `byebug` method calls.

### Public Class Methods

actual_control_port() click to toggle source

The actual port that the control server is started at

    # File lib/byebug/remote.rb, line 25
    def actual_control_port
      control.actual_port
    end

actual_port() click to toggle source

The actual port that the server is started at

    # File lib/byebug/remote.rb, line 20
    def actual_port
      server.actual_port
    end

add_catchpoint(exception) → exception click to toggle source

Adds a new exception to the catchpoints hash.

    static VALUE
    Add_catchpoint(VALUE self, VALUE value)
    {
      UNUSED(self);

      if (TYPE(value) != T_STRING)
        rb_raise(rb_eTypeError, "value of a catchpoint must be String");

      rb_hash_aset(catchpoints, rb_str_dup(value), INT2FIX(0));
      return value;
    }

attach() click to toggle source

Starts byebug, and stops at the first line of user's code.

    # File lib/byebug/attacher.rb, line 10
    def self.attach
      unless started?
        self.mode = :attached

        start
        run_init_script
      end

      current_context.step_out(3, true)
    end

breakpoints → array click to toggle source

Returns an array of breakpoints.

    static VALUE
    Breakpoints(VALUE self)
    {
      UNUSED(self);

      if (NIL_P(breakpoints))
        breakpoints = rb_ary_new();

      return breakpoints;
    }

catchpoints → hash click to toggle source

Returns the catchpoints hash.

    static VALUE
    Catchpoints(VALUE self)
    {
      UNUSED(self);

      return catchpoints;
    }

contexts → array click to toggle source

Returns an array of all contexts.

    static VALUE
    Contexts(VALUE self)
    {
      volatile VALUE list;
      volatile VALUE new_list;
      VALUE context;
      threads_table_t *t_tbl;
      debug_context_t *dc;
      int i;

      UNUSED(self);

      check_started();

      new_list = rb_ary_new();
      list = rb_funcall(rb_cThread, rb_intern("list"), 0);

      for (i = 0; i < RARRAY_LENINT(list); i++)
      {
        VALUE thread = rb_ary_entry(list, i);

        thread_context_lookup(thread, &context);
        rb_ary_push(new_list, context);
      }

      Data_Get_Struct(threads, threads_table_t, t_tbl);
      st_clear(t_tbl->tbl);

      for (i = 0; i < RARRAY_LENINT(new_list); i++)
      {
        context = rb_ary_entry(new_list, i);
        Data_Get_Struct(context, debug_context_t, dc);
        st_insert(t_tbl->tbl, dc->thread, context);
      }

      return new_list;
    }

current_context → context click to toggle source

Returns the current context.

    <i>Note:</i> Byebug.current_context.thread == Thread.current

    static VALUE
    Current_context(VALUE self)
    {
      VALUE context;

      UNUSED(self);

      thread_context_lookup(rb_thread_current(), &context);

      return context;
    }

debug_load(file, stop = false) → nil click to toggle source

Same as Kernel#load but resets current context's frames. `stop` parameter forces byebug to stop at the first line of code in `file`

    static VALUE
    Debug_load(int argc, VALUE *argv, VALUE self)
    {
      VALUE file, stop, context;
      debug_context_t *dc;
      VALUE status = Qnil;
      int state = 0;

      UNUSED(self);

      if (rb_scan_args(argc, argv, "11", &file, &stop) == 1)
        stop = Qfalse;

      Start(self);

      context = Current_context(self);
      Data_Get_Struct(context, debug_context_t, dc);

      dc->calced_stack_size = 1;

      if (RTEST(stop))
        dc->steps = 1;

      rb_load_protect(file, 0, &state);
      if (0 != state)
      {
        status = rb_errinfo();
        byebug_reset_stepping_stop_points(dc);
      }

      return status;
    }

handle_post_mortem() click to toggle source

Saves information about the unhandled exception and gives a byebug prompt back to the user before program termination.

    # File lib/byebug/core.rb, line 76
    def self.handle_post_mortem
      return unless raised_exception

      context = raised_exception.__bb_context

      PostMortemProcessor.new(context).at_line
    end

interrupt() click to toggle source

Interrupts the current thread

    # File lib/byebug/remote.rb, line 32
    def interrupt
      current_context.interrupt
    end

load_settings() click to toggle source

    # File lib/byebug/core.rb, line 61
    def self.load_settings
      Dir.glob(File.join(__dir__, "settings", "*.rb")).each do |file|
        require file
      end

      constants.grep(/[a-z]Setting/).map do |name|
        setting = const_get(name).new
        Byebug::Setting.settings[setting.to_sym] = setting
      end
    end

parse_host_and_port(host_port_spec) click to toggle source

    # File lib/byebug/remote.rb, line 59
    def parse_host_and_port(host_port_spec)
      location = host_port_spec.split(":")
      location[1] ? [location[0], location[1].to_i] : ["localhost", location[0]]
    end

post_mortem = bool click to toggle source

Sets post-moterm flag.

    static VALUE
    Set_post_mortem(VALUE self, VALUE value)
    {
      UNUSED(self);

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

post_mortem? → bool click to toggle source

Returns `true` if post-mortem debugging is enabled.

    static VALUE
    Post_mortem(VALUE self)
    {
      UNUSED(self);

      return post_mortem;
    }

raised_exception → exception click to toggle source

Returns raised exception when in post_mortem mode.

    static VALUE
    Raised_exception(VALUE self)
    {
      UNUSED(self);

      return raised_exception;
    }

spawn(host = "localhost", port = nil) click to toggle source

    # File lib/byebug/attacher.rb, line 21
    def self.spawn(host = "localhost", port = nil)
      require "byebug/core"

      self.wait_connection = true
      start_server(host, port || PORT)
    end

start → bool click to toggle source

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

    static VALUE
    Start(VALUE self)
    {
      if (IS_STARTED)
        return Qfalse;

      catchpoints = rb_hash_new();

      threads = create_threads_table();

      register_tracepoints(self);

      return Qtrue;
    }

start_client(host = "localhost", port = PORT) click to toggle source

Connects to the remote byebug

    # File lib/byebug/remote.rb, line 55
    def start_client(host = "localhost", port = PORT)
      client.start(host, port)
    end

start_control(host = nil, port = PORT + 1) click to toggle source

Starts the remote server control thread

    # File lib/byebug/remote.rb, line 48
    def start_control(host = nil, port = PORT + 1)
      control.start(host, port)
    end

start_server(host = nil, port = PORT) click to toggle source

Starts the remote server main thread

    # File lib/byebug/remote.rb, line 39
    def start_server(host = nil, port = PORT)
      start_control(host, port.zero? ? 0 : port + 1)

      server.start(host, port)
    end

started? → bool click to toggle source

Returns `true` byebug is started.

    static VALUE
    Started(VALUE self)
    {
      UNUSED(self);

      return IS_STARTED ? Qtrue : Qfalse;
    }

stop → bool click to toggle source

This method disables byebug. It returns `true` if byebug was already disabled, otherwise it returns `false`.

    static VALUE
    Stop(VALUE self)
    {
      UNUSED(self);

      if (IS_STARTED)
      {
        clear_tracepoints(self);

        breakpoints = Qnil;
        catchpoints = Qnil;

        return Qfalse;
      }

      return Qtrue;
    }

stoppable?() click to toggle source

    static VALUE
    Stoppable(VALUE self)
    {
      VALUE context;
      debug_context_t *dc;

      if (!IS_STARTED)
        return Qfalse;

      if (!NIL_P(breakpoints) && rb_funcall(breakpoints, idEmpty, 0) == Qfalse)
        return Qfalse;

      if (!NIL_P(catchpoints) && rb_funcall(catchpoints, idEmpty, 0) == Qfalse)
        return Qfalse;

      if (post_mortem == Qtrue)
        return Qfalse;

      if (RTEST(tracing))
        return Qfalse;

      context = Current_context(self);
      if (!NIL_P(context))
      {
        Data_Get_Struct(context, debug_context_t, dc);

        if (dc->steps > 0)
          return Qfalse;
      }

      return Qtrue;
    }

thread_context(thread) → context click to toggle source

Returns context of the thread passed as an argument.

    static VALUE
    Thread_context(VALUE self, VALUE thread)
    {
      VALUE context;

      UNUSED(self);

      check_started();

      thread_context_lookup(thread, &context);

      return context;
    }

tracing = bool click to toggle source

Sets the global tracing flag.

    static VALUE
    Set_tracing(VALUE self, VALUE value)
    {
      UNUSED(self);

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

tracing? → bool click to toggle source

Returns `true` if global tracing is enabled.

    static VALUE
    Tracing(VALUE self)
    {
      UNUSED(self);

      return tracing;
    }

verbose = bool click to toggle source

Sets the global verbose flag for TracePoint API events is enabled.

    static VALUE
    Set_verbose(VALUE self, VALUE value)
    {
      UNUSED(self);

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

verbose? → bool click to toggle source

Returns `true` if global verbose flag for TracePoint API events is enabled.

    static VALUE
    Verbose(VALUE self)
    {
      UNUSED(self);

      return verbose;
    }

### Private Class Methods

client() click to toggle source

    # File lib/byebug/remote.rb, line 66
    def client
      @client ||= Remote::Client.new(Context.interface)
    end

control() click to toggle source

    # File lib/byebug/remote.rb, line 76
    def control
      @control ||= Remote::Server.new(wait_connection: false) do |s|
        context = Byebug.current_context
        interface = RemoteInterface.new(s)

        ControlProcessor.new(context, interface).process_commands
      end
    end

server() click to toggle source

    # File lib/byebug/remote.rb, line 70
    def server
      @server ||= Remote::Server.new(wait_connection: wait_connection) do |s|
        Context.interface = RemoteInterface.new(s)
      end
    end

### Public Instance Methods

run_init_script() click to toggle source

Runs normal byebug initialization scripts.

Reads and executes the commands from init file (if any) in the current working directory. This is only done if the current directory is different from your home directory. Thus, you can have more than one init file, one generic in your home directory, and another, specific to the program you are debugging, in the directory where you invoke byebug.

    # File lib/byebug/core.rb, line 52
    def run_init_script
      rc_dirs.each do |dir|
        rc_file = File.expand_path(File.join(dir, init_file))
        next unless File.exist?(rc_file)

        run_rc_file(rc_file)
      end
    end

### Private Instance Methods

rc_dirs() click to toggle source

List of folders to load rc files from

@note Files will be loaded in the order specified here.

    # File lib/byebug/core.rb, line 102
    def rc_dirs
      [ENV["HOME"], Dir.pwd].compact.uniq
    end

run_rc_file(rc_file) click to toggle source

Runs a initialization script file

    # File lib/byebug/core.rb, line 91
    def run_rc_file(rc_file)
      interface = ScriptInterface.new(rc_file)

      ScriptProcessor.new(nil, interface).process_commands
    end