ruby -rdebug doesn't stop at breakpoints - ruby

# myapp.rb
myvar = 'Hello'
myvar += ' world'
myvar += '!'
puts myvar
puts 'Bye!'
Trying to debug it:
>ruby -rdebug myapp.rb
<...>/ruby-2.7.2-1/lib/ruby/2.7.0/x64-mingw32/continuation.so: warning: callcc is obsolete; use Fiber instead
Debug.rb
Emacs support available.
<...>/ruby-2.7.2-1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:172: if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
(rdb:1) help
Debugger help v.-0.002b
Commands
b[reak] [file:|class:]<line|method>
b[reak] [class.]<line|method>
set breakpoint to some position
. . .
c[ont] run until program ends or hit breakpoint
. . .
Ok, let's do it:
(rdb:1) b myapp.rb:1
Set breakpoint 1 at D:/temp/r/myapp.rb:1
(rdb:1) cont
Hello world!
Bye!
Actual behavior: doesn't stop at breakpoints.
Expected behavior: must stop at breakpoints.
Used gdb for C/C++ and pdb for Python. They have similar interface and work.
The questions are:
Please tell if you can reproduce this problem.
What is the reason of this problem?
Is this a bug or a feature?
How to make the debugger stop at breakpoints?
Could not google the answer. There's an example here (in the end of the page) that, to my mind, doesn't expressly show the expected breakpoint behavior. As the author didn't demonstrate this simple and obvious use case then there must be a problem here.
UPDATE
Checked in Linux -- works as expected.

Try specifying the absolute filename of the program, in other words try running the program as ruby -rdebug $PWD/myapp.rb
I posted a bug report for version 2.7.2 just now:
https://bugs.ruby-lang.org/issues/17492?next_issue_id=17491

Tried with a previous version of Ruby 2.5.3 -- works as expected. The same is on Linux:
$ ruby -rdebug myapp.rb
/usr/lib/x86_64-linux-gnu/ruby/2.5.0/continuation.so: warning: callcc is obsolete; use Fiber instead
Debug.rb
Emacs support available.
myapp.rb:1:myvar = 'Hello'
(rdb:1) b 3
Set breakpoint 1 at myapp.rb:3
(rdb:1) c
Breakpoint 1, toplevel at myapp.rb:3
myapp.rb:3:myvar += '!'
Probably the problem is in the new version or with my installation in Windows.

Related

Getting an undefined local variable error in Ruby when debugging

I have the following script in a file called foo.rb
def foo(msg)
msg
end
def bar
thing = 123
thing
end
debugger
p foo(:hai)
I run the program in debug mode, like so:
ruby --debug -r debug foo.rb
Notice I make sure the stdlib debug is loaded via -r and I also put the ruby environment into debug mode using --debug
So the first output I get is unexpected:
Debug.rb
Emacs support available.
/Users/M/.rbenv/versions/2.1.2/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:57: RUBYGEMS_ACTIVATION_MONITOR.enter
After that, if I press c to 'continue' the program ends with the following error:
Exception `NameError' at foo.rb:10 - undefined local variable or method `debugger' for main:Object foo.rb:10:in `<main>': undefined local variable or method `debugger' for main:Object (NameError)
Can anyone tell me what I'm doing wrong, and how to actually get debug mode to recognise the relevant debugger command (if that's even the correct command to be using; the docs aren't clear at all on this)
Note: I'm not interested in using 3rd party gems in this instance (e.g. pry or ruby-debug). I'm only interested in understanding how to use the stdlib debugger that comes with Ruby
Update
Since this question was answered, I've gone ahead and created a gist for future reference. For anyone stumbling across this thread you might find it useful: https://gist.github.com/Integralist/5658cb218bb50494a1fa
Don't use -r. The entire mechanism by which an interactive debugging sessions is loaded is by the literal line of code require 'debug'.
Your code should look like this:
def foo(msg)
msg
end
def bar
thing = 123
thing
end
require 'debug'
p foo(:hai)
And you should run the program by simply typing ruby <program_name>.rb.

Determine if a program is running in debug mode

I use RubyMine to write and debug my Ruby 2.0 code. It uses ruby-debug-ide for that purpose. I want to know if a program is running in debug mode.
I know there is the Ruby $DEBUG global variable, but as far as I understand ruby-debug-ide didn't change it, because it didn't use the -d ruby flag.
If I debug my file using Rubymine the command executed looks like this:
/home/user/.rvm/rubies/ruby-2.0.0-p353/bin/ruby -e at_exit{sleep(1)};$stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) /home/user/.rvm/gems/ruby-2.0.0-p353/gems/ruby-debug-ide-0.4.22/bin/rdebug-ide --disable-int-handler --port 37737 --dispatcher-port 47992 -- /home/user/file.rb
I tried to use ARGV or $0, to determine if the command line contains the string 'rdebug-ide' but ARGV is an empty array and $0 is just '/home/user/file.rb', how can I get the full command line executed by RubyMine?
This is what I did:
I put the following code in an (rails) action and did a diff on the outputs both in debug and non-debug modes:
puts ENV.to_hash.to_yaml
I noticed that one of the differences is in ENV['RUBYLIB'] (there's also IDE_PROCESS_DISPATCHER, DEBUGGER_STORED_RUBYLIB, RUBYOPT, and DEBUGGER_HOST)
So here's how you'd check:
if ENV['RUBYLIB'] =~ /ruby-debug-ide/
puts 'in debug mode'
else
puts 'not in debug mode'
end
You need the global variable $LOAD_PATH.
a = $LOAD_PATH
a.each do |current_path|
puts 'Debug mode' if current_path.include?('rb/gems')
end
$LOAD_PATH has this line "/home/username/RubyMine-6.0.2/rb/gems" if I use debug mode.

Setting breakpoint in different file has no effect

The ruby debugger does not halt on breakpoints I set in files different from the on the execution starts in. For example, consider these two files, foo.rb:
# foo.rb
class Foo
def bar
puts "baz"
end
end
and main.rb:
# main.rb
require './foo'
Foo.new.bar
I start debugging using ruby -r debug .\main.rb. Now, when I try to set a breakpoint on a specific line in another file using b ./foo.rb:4, I get the message Set breakpoint 1 at foo.rb:4, but when I cont, the program executes to the end, and the debugger never halts. However, if I break on a line in main.rb, e.g. b ./main.rb:3, or a method, e.g. b Foo.bar, the debugger halts as expected.
Why doesn't the debugger halt at breakpoints in files other than the main file?
Update: I have tried this with Ruby 1.9.3 on Windows 7 as well as OS X 10.8; it doesn't work in either environment.
I have also just realized that the debugger quits after the script has run till the end: I start debugging main.rb, use cont, then baz is printed on the console and I'm right back in the shell. Is this the expected behaviour, or might the debugger have crashed?
Wow, that is weird. Not sure if this helps, but maybe you could do this. Step over the require with next so that Foo is loaded then
b Foo:bar
that should at least break on bar

ruby-debug not displaying correct line of code while listing code

I have the following software installed
Ruby
1.8.6
Columnize
0.3.6
linecache
0.43
ruby-debug
0.10.4
ruby-debug-base
0.10.4
There is a piece of code that is almost 22,000 lines long. When rdebug moves to this piece of code, it executes it correctly, but does not display the surrounding correct lines of code or the currently executing line.
For example:
foo.a.b("a string")
Is the method. The following is an example of the code
#around line 2000
#e
#j
#h
.
.
.
#around line 6000
def a
return obj_that_b_is_called_on
end
.
.
.
#around line 20000
def b(string)
puts "Hello World"
puts string
string = a
end
The debugger correctly calls on a and displays the information. However, when b is called, the debugger looks at something similar to the code where #e and #j are. The functions inside b execute correctly, print the correct statements, and I can even evaluate the variable string. Is this a buffer or cache issue? Or is this a setting issue that I can configure?
what does a debugger "backtrace" command show?
Is it correct?
What does the value of
eval caller().each {|l| puts l}
show? (If autoeval is "on", you don't need the initial "eval")
Is that correct?
If caller() isn't giving the right information, it's a problem in Ruby 1.8.6. Without going into details, there have been are various weirdnesses in reporting line recording in Ruby. (Actually, I don't remember which versions have some of the problems I know are there.)

How do I drop to the IRB prompt from a running script?

Can I drop to an IRB prompt from a running Ruby script?
I want to run a script, but then have it give me an IRB prompt at a point in the program with the current state of the program, but not just by running rdebug and having a breakpoint.
Pry (an IRB alternative) also lets you do this, in fact it was designed from the ground up for exactly this use case :)
It's as easy as putting binding.pry at the point you want to start the session:
require 'pry'
x = 10
binding.pry
And inside the session:
pry(main)> puts x
=> 10
Check out the website: http://pry.github.com
Pry let's you:
drop into a session at any point in your code
view method source code
view method documentation (not using RI so you dont have to pre-generate it)
pop in and out of different contexts
syntax highlighting
gist integration
view and replay history
open editors to edit methods using edit obj.my_method syntax
A tonne more great and original features
you can use ruby-debug to get access to irb
require 'rubygems'
require 'ruby-debug'
x = 23
puts "welcome"
debugger
puts "end"
when program reaches debugger you will get access to irb.
apparently it requires a chunk of code to drop into irb.
Here's the link (seems to work well).
http://jameskilton.com/2009/04/02/embedding-irb-into-your-ruby-application
require 'irb'
module IRB
def self.start_session(binding) # call this method to drop into irb
unless #__initialized
args = ARGV
ARGV.replace(ARGV.dup)
IRB.setup(nil)
ARGV.replace(args)
#__initialized = true
end
workspace = WorkSpace.new(binding)
irb = Irb.new(workspace)
#CONF[:IRB_RC].call(irb.context) if #CONF[:IRB_RC]
#CONF[:MAIN_CONTEXT] = irb.context
catch(:IRB_EXIT) do
irb.eval_input
end
end
end
This feature is available from Ruby 2.4. You can just use binding.irb
E.g.
require 'irb'
a = 10
binding.irb
puts a
If you run above code, you will get irb console, so that you can inspect values of local variables and anything else that is in scope.
Source: http://blog.redpanthers.co/new-binding-irb-introduced-ruby-2-4/
Ruby commit: https://github.com/ruby/ruby/commit/493e48897421d176a8faf0f0820323d79ecdf94a
Just add this line to where you want the breakpoint:
require 'ruby-debug';debugger
but i suggest use pry instead of irb, which is super handy, insert the following line instead:
require 'pry'; binding.pry
I'm quite late to the game but if you're loading a script from within irb/pry already, a simple raise also works to pop you back out to the irb/pry prompt. I use this quite often when writing one off scripts within the rails console.

Resources