class DEBUGGER__::Config - debug: Ruby Standard Library Documentation

# class DEBUGGER__::Config

### Public Class Methods

config() click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 66
    def self.config
      @config
    end

config_to_env_hash(config) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 446
    def self.config_to_env_hash config
      CONFIG_MAP.each_with_object({}){|(key, evname), env|
        unless config[key].nil?
          case CONFIG_SET[key][2]
          when :path
            valstr = config[key].map{|e| e.kind_of?(Regexp) ? e.inspect : e}.join(':')
          when :path_map
            valstr = config[key].map{|e| e.join(':')}.join(',')
          else
            valstr = config[key].to_s
          end
          env[evname] = valstr
        end
      }
    end

new(argv) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 70
    def initialize argv
      if self.class.config
        raise 'Can not make multiple configurations in one process'
      end

      config = self.class.parse_argv(argv)

      # apply defaults
      CONFIG_SET.each do |k, config_detail|
        unless config.key?(k)
          default_value = config_detail[3]
          config[k] = parse_config_value(k, default_value)
        end
      end

      update config
    end

parse_argv(argv) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 268
    def self.parse_argv argv
      config = {
        mode: :start,
        no_color: (nc = ENV['NO_COLOR']) && !nc.empty?,
      }
      CONFIG_MAP.each{|key, evname|
        if val = ENV[evname]
          config[key] = parse_config_value(key, val)
        end
      }
      return config if !argv || argv.empty?

      if argv.kind_of? String
        require 'shellwords'
        argv = Shellwords.split(argv)
      end

      require 'optparse'
      require_relative 'version'

      have_shown_version = false

      opt = OptionParser.new do |o|
        o.banner = "#{$0} [options] -- [debuggee options]"
        o.separator ''
        o.version = ::DEBUGGER__::VERSION

        o.separator 'Debug console mode:'
        o.on('-n', '--nonstop', 'Do not stop at the beginning of the script.') do
          config[:nonstop] = '1'
        end

        o.on('-e DEBUG_COMMAND', 'Execute debug command at the beginning of the script.') do |cmd|
          config[:commands] ||= ''
          config[:commands] += cmd + ';;'
        end

        o.on('-x FILE', '--init-script=FILE', 'Execute debug command in the FILE.') do |file|
          config[:init_script] = file
        end
        o.on('--no-rc', 'Ignore ~/.rdbgrc') do
          config[:no_rc] = true
        end
        o.on('--no-color', 'Disable colorize') do
          config[:no_color] = true
        end
        o.on('--no-sigint-hook', 'Disable to trap SIGINT') do
          config[:no_sigint_hook] = true
        end

        o.on('-c', '--command', 'Enable command mode.',
                                'The first argument should be a command name in $PATH.',
                                'Example: \'rdbg -c bundle exec rake test\'') do
          config[:command] = true
        end

        o.separator ''

        o.on('-O', '--open=[FRONTEND]', 'Start remote debugging with opening the network port.',
                                        'If TCP/IP options are not given, a UNIX domain socket will be used.',
                                        'If FRONTEND is given, prepare for the FRONTEND.',
                                        'Now rdbg, vscode and chrome is supported.') do |f|

          case f # some format patterns are not documented yet
          when nil
            config[:open] = true
          when /\A\d\z/
            config[:open] = true
            config[:port] = f.to_i
          when /\A(\S+):(\d+)\z/
            config[:open] = true
            config[:host] = $1
            config[:port] = $2.to_i
          when 'tcp'
            config[:open] = true
            config[:port] ||= 0
          when 'vscode', 'chrome', 'cdp'
            config[:open] = f&.downcase
          else
            raise "Unknown option for --open: #{f}"
          end
        end
        o.on('--sock-path=SOCK_PATH', 'UNIX Domain socket path') do |path|
          config[:sock_path] = path
        end
        o.on('--port=PORT', 'Listening TCP/IP port') do |port|
          config[:port] = port
        end
        o.on('--port-range=PORT_RANGE', 'Number of ports to try to connect to') do |port_range|
          config[:port_range] = port_range
        end
        o.on('--host=HOST', 'Listening TCP/IP host') do |host|
          config[:host] = host
        end
        o.on('--cookie=COOKIE', 'Set a cookie for connection') do |c|
          config[:cookie] = c
        end
        o.on('--session-name=NAME', 'Session name') do |name|
          config[:session_name] = name
        end

        rdbg = 'rdbg'

        o.separator ''
        o.separator '  Debug console mode runs Ruby program with the debug console.'
        o.separator ''
        o.separator "  '#{rdbg} target.rb foo bar'                starts like 'ruby target.rb foo bar'."
        o.separator "  '#{rdbg} -- -r foo -e bar'                 starts like 'ruby -r foo -e bar'."
        o.separator "  '#{rdbg} -c rake test'                     starts like 'rake test'."
        o.separator "  '#{rdbg} -c -- rake test -t'               starts like 'rake test -t'."
        o.separator "  '#{rdbg} -c bundle exec rake test'         starts like 'bundle exec rake test'."
        o.separator "  '#{rdbg} -O target.rb foo bar'             starts and accepts attaching with UNIX domain socket."
        o.separator "  '#{rdbg} -O --port 1234 target.rb foo bar' starts accepts attaching with TCP/IP localhost:1234."
        o.separator "  '#{rdbg} -O --port 1234 -- -r foo -e bar'  starts accepts attaching with TCP/IP localhost:1234."
        o.separator "  '#{rdbg} target.rb -O chrome --port 1234'  starts and accepts connecting from Chrome Devtools with localhost:1234."

        o.separator ''
        o.separator 'Attach mode:'
        o.on('-A', '--attach', 'Attach to debuggee process.') do
          config[:mode] = :attach
        end

        o.separator ''
        o.separator '  Attach mode attaches the remote debug console to the debuggee process.'
        o.separator ''
        o.separator "  '#{rdbg} -A'           tries to connect via UNIX domain socket."
        o.separator "  #{' ' * rdbg.size}                If there are multiple processes are waiting for the"
        o.separator "  #{' ' * rdbg.size}                debugger connection, list possible debuggee names."
        o.separator "  '#{rdbg} -A path'      tries to connect via UNIX domain socket with given path name."
        o.separator "  '#{rdbg} -A port'      tries to connect to localhost:port via TCP/IP."
        o.separator "  '#{rdbg} -A host port' tries to connect to host:port via TCP/IP."

        o.separator ''
        o.separator 'Other options:'

        o.on('-v', 'Show version number') do
          puts o.ver
          have_shown_version = true
        end

        o.on('--version', 'Show version number and exit') do
          puts o.ver
          exit
        end

        o.on("-h", "--help", "Print help") do
          puts o
          exit
        end

        o.on('--util=NAME', 'Utility mode (used by tools)') do |name|
          require_relative 'client'
          Client.util(name)
          exit
        end

        o.on('--stop-at-load', 'Stop immediately when the debugging feature is loaded.') do
          config[:stop_at_load] = true
        end

        o.separator ''
        o.separator 'NOTE'
        o.separator '  All messages communicated between a debugger and a debuggee are *NOT* encrypted.'
        o.separator '  Please use the remote debugging feature carefully.'
      end

      opt.parse!(argv)

      if argv.empty?
        case
        when have_shown_version && config[:mode] == :start
          exit
        end
      end

      config
    end

parse_config_value(name, valstr) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 227
    def self.parse_config_value name, valstr
      return valstr unless valstr.kind_of? String

      case CONFIG_SET[name][2]
      when :bool
        case valstr
        when '1', 'true', 'TRUE', 'T'
          true
        else
          false
        end
      when :int
        valstr.to_i
      when :loglevel
        if DEBUGGER__::LOG_LEVELS[s = valstr.to_sym]
          s
        else
          raise "Unknown loglevel: #{valstr}"
        end
      when :forkmode
        case sym = valstr.to_sym
        when :parent, :child, :both, nil
          sym
        else
          raise "unknown fork mode: #{sym}"
        end
      when :path # array of String
        valstr.split(/:/).map{|e|
          if /\A\/(.+)\/\z/ =~ e
            Regexp.compile $1
          else
            e
          end
        }
      when :path_map
        valstr.split(',').map{|e| e.split(':')}
      else
        valstr
      end
    end

### Public Instance Methods

[](key) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 92
    def [](key)
      config[key]
    end

[]=(key, val) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 96
    def []=(key, val)
      set_config(key => val)
    end

append_config(key, val) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 113
    def append_config key, val
      conf = config.dup

      if CONFIG_SET[key]
        if CONFIG_SET[key][2] == :path
          conf[key] = [*conf[key], *parse_config_value(key, val)];
        else
          raise "not an Array type: #{key}"
        end
      else
        raise "Unknown configuration: #{key}"
      end

      update conf
    end

inspect() click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 88
    def inspect
      config.inspect
    end

set_config(**kw) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 100
    def set_config(**kw)
      conf = config.dup
      kw.each{|k, v|
        if CONFIG_MAP[k]
          conf[k] = parse_config_value(k, v) # TODO: ractor support
        else
          raise "Unknown configuration: #{k}"
        end
      }

      update conf
    end

update(conf) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 129
    def update conf
      old_conf = self.class.instance_variable_get(:@config) || {}

      # TODO: Use Ractor.make_shareable(conf)
      self.class.instance_variable_set(:@config, conf.freeze)

      # Post process
      if_updated old_conf, conf, :keep_alloc_site do |old, new|
        if new
          require 'objspace'
          ObjectSpace.trace_object_allocations_start
        end

        if old && !new
          ObjectSpace.trace_object_allocations_stop
        end
      end

      if_updated old_conf, conf, :postmortem do |_, new_p|
        if defined?(SESSION)
          SESSION.postmortem = new_p
        end
      end

      if_updated old_conf, conf, :sigdump_sig do |old_sig, new_sig|
        setup_sigdump old_sig, new_sig
      end

      if_updated old_conf, conf, :no_sigint_hook do |old, new|
        if defined?(SESSION)
          SESSION.set_no_sigint_hook old, new
        end
      end

      if_updated old_conf, conf, :irb_console do |old, new|
        if defined?(SESSION) && SESSION.active?
          # irb_console is switched from true to false
          if old
            SESSION.deactivate_irb_integration
          # irb_console is switched from false to true
          else
            if CONFIG[:open]
              SESSION.instance_variable_get(:@ui).puts "\nIRB is not supported on the remote console."
            else
              SESSION.activate_irb_integration
            end
          end
        end
      end
    end

### Private Instance Methods

config() click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 219
            def config
      self.class.config
    end

disable_sigdump(old_sig) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 201
            def disable_sigdump old_sig
      trap(old_sig, @sigdump_sig_prev)
      @sigdump_sig_prev = nil
    end

enable_sigdump(sig) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 185
            def enable_sigdump sig
      @sigdump_sig_prev = trap(sig) do
        str = []
        str << "Simple sigdump on #{Process.pid}"
        Thread.list.each{|th|
          str << "Thread: #{th}"
          th.backtrace.each{|loc|
            str << "  #{loc}"
          }
          str << ''
        }

        STDERR.puts str
      end
    end

if_updated(old_conf, new_conf, key) { |old, new| ... } click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 180
            def if_updated old_conf, new_conf, key
      old, new = old_conf[key], new_conf[key]
      yield old, new if old != new
    end

parse_config_value(name, valstr) click to toggle source

    # File debug-1.10.0/lib/debug/config.rb, line 223
            def parse_config_value name, valstr
      self.class.parse_config_value name, valstr
    end

setup_sigdump(old_sig = nil, sig = CONFIG[:sigdump_sig]) click to toggle source

emergency simple sigdump. Use ‘sigdump` gem for more rich features.

    # File debug-1.10.0/lib/debug/config.rb, line 208
            def setup_sigdump old_sig = nil, sig = CONFIG[:sigdump_sig]
      if !old_sig && sig
        enable_sigdump sig
      elsif old_sig && !sig
        disable_sigdump old_sig
      elsif old_sig && sig
        disable_sigdump old_sig
        enable_sigdump sig
      end
    end