Skip to content

Commit

Permalink
Prevent ghost breakpoints by making sure we can't have dangling trace…
Browse files Browse the repository at this point in the history
…points

Any time we disable a breakpoint or re-set the `tp` instance variable,
we need to make sure any previous trace points are disabled or else they
might continue to suspend execution even after breakpoint removal
  • Loading branch information
vinistock committed Jul 31, 2023
1 parent 1450ad0 commit ea383be
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 4 deletions.
5 changes: 5 additions & 0 deletions lib/debug/breakpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ def initialize path, line, cond: nil, oneshot: false, hook_call: true, command:
def setup
return unless @type

# There are scenarios where `setup` is invoked more than once. If we don't disable any possible previous trace
# point events, then we will update the `@tp` reference with a new instance but the previous one will still be
# activated, leading to the debugger suspending in breakpoints that were previously removed
disable

@tp = TracePoint.new(@type) do |tp|
if @cond
next unless safe_eval tp.binding, @cond
Expand Down
12 changes: 8 additions & 4 deletions lib/debug/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1747,11 +1747,15 @@ def on_load iseq, src
end.each do |_key, bp|
if !bp.iseq
bp.try_activate iseq
elsif reloaded
elsif reloaded && (iseq.first_lineno..iseq.last_line).cover?(bp.line)
@bps.delete bp.key # to allow duplicate
if nbp = LineBreakpoint.copy(bp, iseq)
add_bp nbp
end

# When we delete a breakpoint from the @bps hash, we also need to deactivate it or else its tracepoint event
# will continue to be enabled and we'll suspend on ghost breakpoints
bp.delete

nbp = LineBreakpoint.copy(bp, iseq)
add_bp nbp
end
end
else # !file_path => file_path is not existing
Expand Down

0 comments on commit ea383be

Please sign in to comment.