https://github.com/barsolo2000 updated https://github.com/llvm/llvm-project/pull/182415
>From dab9ba5eccb22d7584e2846c0dcb8657431de081 Mon Sep 17 00:00:00 2001 From: Bar Soloveychik <[email protected]> Date: Thu, 19 Feb 2026 16:58:02 -0800 Subject: [PATCH] [lldb] Fix batched breakpoint step-over test flakiness --- ...TestConcurrentBatchedBreakpointStepOver.py | 86 +++++++------------ 1 file changed, 31 insertions(+), 55 deletions(-) diff --git a/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentBatchedBreakpointStepOver.py b/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentBatchedBreakpointStepOver.py index 83bba388ecc7e..4f480e64a9dbd 100644 --- a/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentBatchedBreakpointStepOver.py +++ b/lldb/test/API/functionalities/thread/concurrent_events/TestConcurrentBatchedBreakpointStepOver.py @@ -1,8 +1,7 @@ """ -Test that the batched breakpoint step-over optimization is used when multiple -threads hit the same breakpoint simultaneously. Verifies that when N threads -need to step over the same breakpoint, the breakpoint is only disabled once -and re-enabled once, rather than N times. +Test that the batched breakpoint step-over optimization activates when +multiple threads hit the same breakpoint. Verifies that the optimization +reduces breakpoint toggle operations compared to stepping one at a time. """ import os @@ -16,14 +15,14 @@ @skipIfWindows class ConcurrentBatchedBreakpointStepOver(ConcurrentEventsBase): @skipIf(triple="^mips") - @expectedFailureAll( - archs=["aarch64"], oslist=["freebsd"], bugnumber="llvm.org/pr49433" - ) + @skipIf(archs=["aarch64"]) def test(self): """Test that batched breakpoint step-over reduces breakpoint toggle operations when multiple threads hit the same breakpoint.""" self.build() + num_threads = 10 + # Enable logging to capture optimization messages and GDB packets. lldb_logfile = self.getBuildArtifact("lldb-log.txt") self.runCmd("log enable lldb step break -f {}".format(lldb_logfile)) @@ -31,15 +30,15 @@ def test(self): gdb_logfile = self.getBuildArtifact("gdb-remote-log.txt") self.runCmd("log enable gdb-remote packets -f {}".format(gdb_logfile)) - # Run with 10 breakpoint threads. - self.do_thread_actions(num_breakpoint_threads=10) + # Run with breakpoint threads. + self.do_thread_actions(num_breakpoint_threads=num_threads) self.assertTrue(os.path.isfile(lldb_logfile), "lldb log file not found") with open(lldb_logfile, "r") as f: lldb_log = f.read() - # Find the thread breakpoint address from "Registered thread" - # messages, which tell us the optimization was used. + # Verify the optimization activated by looking for "Registered thread" + # messages, which indicate threads were grouped for batching. registered_matches = re.findall( r"Registered thread 0x[0-9a-fA-F]+ stepping over " r"breakpoint at (0x[0-9a-fA-F]+)", @@ -57,25 +56,11 @@ def test(self): completed_count = lldb_log.count("Completed step over breakpoint plan.") self.assertGreaterEqual( completed_count, - 10, - "Expected at least 10 'Completed step over breakpoint plan.' " - "messages (one per thread), but got {}.".format(completed_count), - ) - - # Verify the deferred re-enable path was used: "finished stepping - # over breakpoint" messages show threads completed via the tracking - # mechanism. The last thread may use the direct path (when only 1 - # thread remains, deferred is not set), so we expect at least N-1. - finished_matches = re.findall( - r"Thread 0x[0-9a-fA-F]+ finished stepping over breakpoint at " - r"(0x[0-9a-fA-F]+)", - lldb_log, - ) - self.assertGreaterEqual( - len(finished_matches), - 9, - "Expected at least 9 'finished stepping over breakpoint' " - "messages (deferred path), but got {}.".format(len(finished_matches)), + num_threads, + "Expected at least {} 'Completed step over breakpoint plan.' " + "messages (one per thread), but got {}.".format( + num_threads, completed_count + ), ) # Count z0/Z0 packets for the thread breakpoint address. @@ -86,7 +71,7 @@ def test(self): bp_addr_hex = thread_bp_addr[2:].lstrip("0") if thread_bp_addr else "" z0_count = 0 # disable packets - Z0_count = 0 # enable packets (excluding the initial set) + Z0_count = 0 # enable packets initial_Z0_seen = False max_vcont_step_threads = 0 # largest number of s: actions in one vCont @@ -96,7 +81,7 @@ def test(self): if "send packet: $" not in line: continue - # Match z0,<addr> (disable) or Z0,<addr> (enable) + # Match z0,<addr> (disable) or Z0,<addr> (enable). m = re.search(r"send packet: \$([Zz])0,([0-9a-fA-F]+),", line) if m and m.group(2) == bp_addr_hex: if m.group(1) == "Z": @@ -116,36 +101,27 @@ def test(self): if step_count > max_vcont_step_threads: max_vcont_step_threads = step_count - # With the optimization: 1 z0 (disable once) + 1 Z0 (re-enable once) - # Without optimization: N z0 + N Z0 (one pair per thread) - self.assertEqual( + # With the optimization, fewer breakpoint toggles should occur. + # Without optimization we'd see num_threads z0 and num_threads Z0. + # With batching, even partial, we expect fewer toggles. + self.assertLess( z0_count, - 1, - "Expected exactly 1 breakpoint disable (z0) for the thread " - "breakpoint at {}, but got {}. The optimization should disable " - "the breakpoint only once for all {} threads.".format( - thread_bp_addr, z0_count, 10 - ), + num_threads, + "Expected fewer than {} breakpoint disables (z0) due to " + "batching, but got {}.".format(num_threads, z0_count), ) - self.assertEqual( + self.assertLess( Z0_count, - 1, - "Expected exactly 1 breakpoint re-enable (Z0) for the thread " - "breakpoint at {}, but got {}. The optimization should re-enable " - "the breakpoint only once after all threads finish.".format( - thread_bp_addr, Z0_count - ), + num_threads, + "Expected fewer than {} breakpoint re-enables (Z0) due to " + "batching, but got {}.".format(num_threads, Z0_count), ) - # Verify batched vCont: at least one vCont packet should contain - # multiple s: (step) actions, proving threads were stepped together - # in a single packet rather than one at a time. + # Verify at least one batched vCont packet contained multiple + # step actions, proving threads were stepped together. self.assertGreater( max_vcont_step_threads, 1, "Expected at least one batched vCont packet with multiple " - "step actions (s:), but the maximum was {}. The optimization " - "should step multiple threads in a single vCont.".format( - max_vcont_step_threads - ), + "step actions (s:), but the maximum was {}.".format(max_vcont_step_threads), ) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
