byebug
byebug copied to clipboard
`next`ing over Forwardable method calls continues until next breakpoint
Problem description
Using next
in certain situations continues until the next breakpoint / end of program instead of stopping on the next statement.
try this script:
#!/usr/bin/env ruby
require 'byebug'
require 'forwardable'
class BoringLogger
def info(*args)
puts "BORING LOGGER: #{args}"
end
end
class WrappedLogger
extend Forwardable
def_delegators :@logger, :info
def initialize
@logger = BoringLogger.new
end
# Uncomment this method and the `next` command will work properly
# def info(*args)
# @logger.info(*args)
# end
end
byebug
puts "THIS IS LINE A"
wrapped_logger = WrappedLogger.new
wrapped_logger.info('hello world') # `next`ing over this line in the debugger will go too far
puts "THIS IS LINE B"
byebug
puts "THIS IS LINE C"
Expected behavior
Using the next
command on the wrapped_logger.info
line lands on the puts "THIS IS LINE B"
line.
Actual behavior
Execution continues until the next byebug
statement.
Steps to reproduce
byebug 10.0.2, ruby 2.5.1
The real-world scenario this canned example reproduces is Selenium::WebDriver::Logger -- we find that next
blows through the execution of our selenium scripts if that logger is allowed to log.
Haven't tried it on any other versions so I don't know if it's a regression or it's always been like this.
@deivid-rodriguez I think this is caused by this Ruby issue: https://bugs.ruby-lang.org/issues/15303. Could I ask you to participate in that discussion?
For context, I think this is why next
breaks from https://bugs.ruby-lang.org/issues/15313:
The popular debugger "byebug" relies on tracepoint events to implement a few core functionality such as "next". The "next" command needs to pause execution when the VM reaches the next line on the same stack frame. As there is no direct way, using the public API, to tell the execution progress of a frame, Byebug keeps track of the currently executing frame by maintaining a counter using the "call" and "return" tracepoint event. https://github.com/deivid-rodriguez/byebug/blob/58ee5114aa856ec49483532a86fd159a877dd6ab/ext/byebug/byebug.c#L162-L170 Byebug's counter becomes incorrect when the interpreter performs a tail call, since after a tail call, the "return" event doesn't fire for the caller. #15303 This causes the "next" command to misbehave when stepping over code that performs tail call. https://github.com/deivid-rodriguez/byebug/issues/481
Absolutely @XrXr, I'll have a look at this and join the ruby-core ticket. :+1: