Default options to ::start
Of course MS Windows has to be different
the port number used for remote debugging
gdb-style annotation mode. Used in GNU Emacs interface
interface modules provide handler
object
if true
, checks the modification time of source files and
reloads if it was modified
If set, a string to look for in caller() and is used to see if the call stack is truncated.
in remote mode, wait for the remote connection
# File lib/ruby-debug-base.rb, line 148 def handle_post_mortem(exp) return if !exp || !exp.__debug_context || exp.__debug_context.stack_size == 0 Debugger.suspend orig_tracing = Debugger.tracing, Debugger.current_context.tracing Debugger.tracing = Debugger.current_context.tracing = false Debugger.last_exception = exp handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line) ensure Debugger.tracing, Debugger.current_context.tracing = orig_tracing Debugger.resume end
Interrupts the current thread
# File lib/ruby-debug-base.rb, line 78 def interrupt current_context.interrupt end
Interrupts the last debugged thread
# File lib/ruby-debug-base.rb, line 85 def interrupt_last if context = last_context return nil unless context.thread.alive? context.interrupt end context end
Activates the post-mortem mode. There are two ways of using it:
By calling ::post_mortem method without a block, you install at_exit hook that intercepts any unhandled by your script exceptions and enables 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 ::post_mortem, e.g.
def offender raise 'error' end Debugger.post_mortem do ... offender ... end
# File lib/ruby-debug-base.rb, line 127 def post_mortem if block_given? old_post_mortem = self.post_mortem? begin self.post_mortem = true yield rescue Exception => exp handle_post_mortem(exp) raise ensure self.post_mortem = old_post_mortem end else return if post_mortem? self.post_mortem = true debug_at_exit do handle_post_mortem($!) if $! && post_mortem? end end end
Runs normal debugger 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 ruby-debug.
# File lib/ruby-debug.rb, line 135 def run_init_script(out = handler.interface) cwd_script_file = File.expand_path(File.join(".", INITFILE)) run_script(cwd_script_file, out) if File.exists?(cwd_script_file) home_script_file = File.expand_path(File.join(HOME_DIR, INITFILE)) run_script(home_script_file, out) if File.exists?(home_script_file) and cwd_script_file != home_script_file end
Runs a script file
# File lib/ruby-debug.rb, line 147 def run_script(file, out = handler.interface, verbose=false) interface = ScriptInterface.new(File.expand_path(file), out) processor = ControlCommandProcessor.new(interface) processor.process_commands(verbose) end
Returns setting object. Use ::settings[] and ::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
# File lib/ruby-debug/command.rb, line 224 def self.settings Command.settings end
# File lib/ruby-debug-base.rb, line 93 def source_reload LineCache::clear_file_cache end
::start -> bool ::start { ... } -> 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 ::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 ::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.
# File lib/ruby-debug-base.rb, line 200 def start(options={}, &block) options = Debugger::DEFAULT_START_SETTINGS.merge(options) if options[:init] Debugger.const_set('ARGV', ARGV.clone) unless defined? Debugger::ARGV Debugger.const_set('PROG_SCRIPT', $0) unless defined? Debugger::PROG_SCRIPT Debugger.const_set('INITIAL_DIR', Dir.pwd) unless defined? Debugger::INITIAL_DIR end Debugger.tracing = options[:tracing] unless options[:tracing].nil? retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block) if options[:post_mortem] post_mortem end return retval end
Connects to the remote debugger
# File lib/ruby-debug.rb, line 103 def start_client(host = 'localhost', port = PORT) require "socket" interface = Debugger::LocalInterface.new socket = TCPSocket.new(host, port) puts "Connected." catch(:exit) do while (line = socket.gets) case line when %r^PROMPT (.*)$/ input = interface.read_command($1) throw :exit unless input socket.puts input when %r^CONFIRM (.*)$/ input = interface.confirm($1) throw :exit unless input socket.puts input else print line end end end socket.close end
Starts a remote debugger.
# File lib/ruby-debug.rb, line 47 def start_remote(host = nil, port = PORT) return if @thread self.interface = nil start if port.kind_of?(Array) cmd_port, ctrl_port = port else cmd_port, ctrl_port = port, port + 1 end ctrl_port = start_control(host, ctrl_port) yield if block_given? mutex = Mutex.new proceed = ConditionVariable.new server = TCPServer.new(host, cmd_port) @cmd_port = cmd_port = server.addr[1] @thread = DebugThread.new do while (session = server.accept) self.interface = RemoteInterface.new(session) if wait_connection mutex.synchronize do proceed.signal end end end end if wait_connection mutex.synchronize do proceed.wait(mutex) end end end