[Lldb-commits] [lldb] 043e778 - lldb] Fix two issues causing TestEvents.py flakiness (#194438)

via lldb-commits lldb-commits at lists.llvm.org
Mon Apr 27 15:53:00 PDT 2026


Author: Jonas Devlieghere
Date: 2026-04-27T15:52:56-07:00
New Revision: 043e778f85f60b654547f2104bca32fdbed2eafd

URL: https://github.com/llvm/llvm-project/commit/043e778f85f60b654547f2104bca32fdbed2eafd
DIFF: https://github.com/llvm/llvm-project/commit/043e778f85f60b654547f2104bca32fdbed2eafd.diff

LOG: lldb] Fix two issues causing TestEvents.py flakiness (#194438)

This PR fixes two issues that contribute to `TestEvents.py` being flaky
in CI:

1. `ProcessEventData::DoOnRemoval` runs the full stop-handling logic
(like `ShouldStop` and `RunStopHooks`) every time an event is consumed
from any listener. When the primary listener consumes an event and then
the shadow listener consumes the same event, the logic runs twice. The
second execution can race with subsequent event processing. Fix this by
incrementing `m_update_state` after the first successful run so
secondary listeners skip the full logic.

2. Target::RunStopHooks updates `m_latest_stop_hook_id` (marking a stop
as "handled") before checking whether any threads have stop reasons. If
the check fails and hooks don't run, the stop ID is already consumed,
preventing hooks from ever running for that stop. Fix this by deferring
the update until we're certain we'll actually run hooks.

Added: 
    

Modified: 
    lldb/source/Target/Process.cpp
    lldb/source/Target/Target.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 86ce11522ab69..8151a4f929d47 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -4481,7 +4481,10 @@ bool Process::ProcessEventData::ForwardEventToPendingListeners(
 
   // For state changed events, if the update state is zero, we are handling
   // this on the private state thread.  We should wait for the public event.
-  return m_update_state == 1;
+  // After the primary listener processes it in DoOnRemoval, m_update_state
+  // is incremented from 1 to 2, which is when we forward to pending
+  // (secondary) listeners.
+  return m_update_state > 1;
 }
 
 void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
@@ -4498,12 +4501,14 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) {
   // pulled off of the private process event queue, and then any number of
   // times, first when it gets pulled off of the public event queue, then other
   // times when we're pretending that this is where we stopped at the end of
-  // expression evaluation.  m_update_state is used to distinguish these three
-  // cases; it is 0 when we're just pulling it off for private handling, and >
-  // 1 for expression evaluation, and we don't want to do the breakpoint
-  // command handling then.
+  // expression evaluation.  m_update_state is used to distinguish these
+  // cases; it is 0 when we're just pulling it off for private handling, 1
+  // when the primary public listener consumes it, and > 1 after that (e.g.
+  // secondary listeners or expression evaluation) where we don't want to
+  // redo the breakpoint command handling or stop hooks.
   if (m_update_state != 1)
     return;
+  m_update_state++;
 
   process_sp->SetPublicState(
       m_state, Process::ProcessEventData::GetRestartedFromEvent(event_ptr));

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 27ddc4e7e5092..8a518685e716b 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3162,8 +3162,6 @@ bool Target::RunStopHooks(bool at_initial_stop) {
   if (last_natural_stop != 0 && m_latest_stop_hook_id == last_natural_stop)
     return false;
 
-  m_latest_stop_hook_id = last_natural_stop;
-
   std::vector<ExecutionContext> exc_ctx_with_reasons;
 
   ThreadList &cur_threadlist = m_process_sp->GetThreadList();
@@ -3195,6 +3193,8 @@ bool Target::RunStopHooks(bool at_initial_stop) {
     }
   }
 
+  m_latest_stop_hook_id = last_natural_stop;
+
   StreamSP output_sp = m_debugger.GetAsyncOutputStream();
   llvm::scope_exit on_exit([output_sp] { output_sp->Flush(); });
 


        


More information about the lldb-commits mailing list