Skip to content

Commit 33d9c25

Browse files
st0012ko1
authored andcommitted
CheckBreakpoint should only stop at the first condition fulfillment line
When a condition is fulfilled (e.g. a >= 1), it usually remains true for at least a while. However, under the current implementation, it'll stops at every single line after the condition becomes true, which is annoying. So this PR introduces an extra state to make sure the BP doesn't stop repeatedly after the condition is fulfilled.
1 parent 4b2219b commit 33d9c25

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

lib/debug/breakpoint.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,13 @@ def setup
326326
next if ThreadClient.current.management?
327327
next if skip_path?(tp.path)
328328

329-
if safe_eval tp.binding, @cond
330-
suspend
329+
if safe_eval(tp.binding, @cond)
330+
unless fulfilled_on_current_thread?
331+
set_fulfilled_on_current_thread
332+
suspend
333+
end
334+
else
335+
set_unfulfilled_on_current_thread
331336
end
332337
}
333338
end
@@ -337,6 +342,20 @@ def to_s
337342
s += super
338343
s
339344
end
345+
346+
private
347+
348+
def fulfilled_on_current_thread?
349+
ThreadClient.current.check_bp_fulfilled?(self)
350+
end
351+
352+
def set_fulfilled_on_current_thread
353+
ThreadClient.current.set_check_bp_state(self, true)
354+
end
355+
356+
def set_unfulfilled_on_current_thread
357+
ThreadClient.current.set_check_bp_state(self, false)
358+
end
340359
end
341360

342361
class WatchIVarBreakpoint < Breakpoint

lib/debug/thread_client.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ def initialize id, q_evt, q_cmd, thr = Thread.current
9595
@obj_map = {} # { object_id => obj } for CDP
9696
@recorder = nil
9797
@mode = :waiting
98+
# every thread should maintain its own CheckBreakpoint fulfillment state
99+
@check_bp_fulfillment_map = {} # { check_bp => boolean }
98100
set_mode :running
99101
thr.instance_variable_set(:@__thread_client_id, id)
100102

@@ -337,6 +339,14 @@ def step_tp iter, events = [:line, :b_return, :return]
337339
end
338340
end
339341

342+
def set_check_bp_state(bp, state)
343+
@check_bp_fulfillment_map[bp] = state
344+
end
345+
346+
def check_bp_fulfilled?(bp)
347+
@check_bp_fulfillment_map[bp]
348+
end
349+
340350
## cmd helpers
341351

342352
if TracePoint.respond_to? :allow_reentry

test/debug/break_test.rb

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,11 @@ def program
645645
2| a += 1
646646
3| a += 2
647647
4| a += 3
648-
5|
649-
6| binding.b
648+
5| a = 0
649+
6| a = 1
650+
7| a = 2
651+
8| a = 3
652+
9| binding.b
650653
RUBY
651654
end
652655

@@ -671,6 +674,22 @@ def test_conditional_breakpoint_shows_error
671674
end
672675
end
673676

677+
def test_conditional_breakpoint_ignores_unchanged_true_condition
678+
debug_code(program) do
679+
type 'break if: a > 0'
680+
type 'c'
681+
assert_line_num(2) # stopped by line 1
682+
# the state remains fulfilled so the next 2 lines don't trigger stoppage
683+
type 'c'
684+
# line 5 changes the state. so the next true condition will stop the program again
685+
assert_line_num(7) # stopped by line 6
686+
type 'c'
687+
# the state remains fulfilled again, so the line 7 doesn't trigger stoppage
688+
assert_line_num(9)
689+
type 'c'
690+
end
691+
end
692+
674693
class PathOptionTest < TestCase
675694
def extra_file
676695
<<~RUBY
@@ -712,10 +731,6 @@ def test_the_path_option_supersede_skip_path_config
712731
assert_line_num(3)
713732
assert_line_text(/201/)
714733
type 'c'
715-
# this stop is because check bp stops at every line after the condition is fulfilled, which is another issue
716-
# see https://github.com/ruby/debug/issues/406 for more about the issue
717-
assert_line_num(4)
718-
type 'c'
719734
end
720735
end
721736

0 commit comments

Comments
 (0)