[Lldb-commits] [lldb] [lldb-dap] subscribe to target events at the broadcaster-manager level (PR #201866)

via lldb-commits lldb-commits at lists.llvm.org
Fri Jun 5 08:42:12 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Charles Zablit (charles-zablit)

<details>
<summary>Changes</summary>

https://github.com/llvm/llvm-project/pull/200133 added `wait_for_module_events()` assertions to `TestDAP_attachCommands.py` and `TestDAP_launch_extra_launch_commands.py`. However, `SetTarget` is called after the `Run*Commands`, so this fails on Windows, because it loads modules early during the process startup. The module-load events are not listened to.

This patch moves the event subscription to `DAPSessionManager::GetEventThreadForDebugger` and uses `StartListeningForEventClass` so any target created in this debugger automatically gets the listener attached. This is the same pattern we already use for `SBThread` events.

This is a follow up to https://github.com/llvm/llvm-project/pull/201796 which skipped the tests.

---
Full diff: https://github.com/llvm/llvm-project/pull/201866.diff


5 Files Affected:

- (modified) lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py (-1) 
- (modified) lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py (+1-2) 
- (modified) lldb/tools/lldb-dap/DAP.cpp (+1-18) 
- (modified) lldb/tools/lldb-dap/DAPSessionManager.cpp (+21-1) 
- (modified) lldb/tools/lldb-dap/EventHelper.cpp (+2-2) 


``````````diff
diff --git a/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py b/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py
index 525783b3785fb..f24a32edbaa7b 100644
--- a/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py
+++ b/lldb/test/API/tools/lldb-dap/attach-commands/TestDAP_attachCommands.py
@@ -12,7 +12,6 @@
 class TestDAP_attachCommands(lldbdap_testcase.DAPTestCaseBase):
     SHARED_BUILD_TESTCASE = False
 
-    @skipIfWindows  # Wait for module events fails.
     @skipIfNetBSD  # Hangs on NetBSD as well
     def test_commands(self):
         """
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py
index cc3c4764a5fd7..ad48af6364aba 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py
@@ -2,7 +2,7 @@
 Test lldb-dap launch request.
 """
 
-from lldbsuite.test.decorators import skipIf, skipIfWindows
+from lldbsuite.test.decorators import skipIf
 from lldbsuite.test.lldbtest import line_number
 import lldbdap_testcase
 
@@ -12,7 +12,6 @@ class TestDAP_launch_extra_launch_commands(lldbdap_testcase.DAPTestCaseBase):
     Tests the "launchCommands" with extra launching settings
     """
 
-    @skipIfWindows  # Wait for module events fails.
     # Flakey on 32-bit Arm Linux.
     @skipIf(oslist=["linux"], archs=["arm$"])
     def test(self):
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index cb34c7b2fd1e8..efd10698b9fb8 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -786,24 +786,7 @@ lldb::SBTarget DAP::CreateTarget(lldb::SBError &error) {
   return target;
 }
 
-void DAP::SetTarget(const lldb::SBTarget target) {
-  this->target = target;
-
-  if (target.IsValid()) {
-    // Configure breakpoint event listeners for the target.
-    lldb::SBListener listener = this->debugger.GetListener();
-    listener.StartListeningForEvents(
-        this->target.GetBroadcaster(),
-        lldb::SBTarget::eBroadcastBitBreakpointChanged |
-            lldb::SBTarget::eBroadcastBitModulesLoaded |
-            lldb::SBTarget::eBroadcastBitModulesUnloaded |
-            lldb::SBTarget::eBroadcastBitSymbolsLoaded |
-            lldb::SBTarget::eBroadcastBitSymbolsChanged |
-            lldb::SBTarget::eBroadcastBitNewTargetCreated);
-    listener.StartListeningForEvents(this->broadcaster,
-                                     eBroadcastBitStopEventThread);
-  }
-}
+void DAP::SetTarget(const lldb::SBTarget target) { this->target = target; }
 
 bool DAP::HandleObject(const Message &M) {
   TelemetryDispatcher dispatcher(&debugger);
diff --git a/lldb/tools/lldb-dap/DAPSessionManager.cpp b/lldb/tools/lldb-dap/DAPSessionManager.cpp
index aa1054f86e143..7e0cac638b45b 100644
--- a/lldb/tools/lldb-dap/DAPSessionManager.cpp
+++ b/lldb/tools/lldb-dap/DAPSessionManager.cpp
@@ -119,6 +119,15 @@ DAPSessionManager::GetEventThreadForDebugger(lldb::SBDebugger debugger,
   listener.StartListeningForEventClass(
       debugger, lldb::SBThread::GetBroadcasterClassName(),
       lldb::SBThread::eBroadcastBitStackChanged);
+  // Listen for target events.
+  listener.StartListeningForEventClass(
+      debugger, lldb::SBTarget::GetBroadcasterClassName(),
+      lldb::SBTarget::eBroadcastBitBreakpointChanged |
+          lldb::SBTarget::eBroadcastBitModulesLoaded |
+          lldb::SBTarget::eBroadcastBitModulesUnloaded |
+          lldb::SBTarget::eBroadcastBitSymbolsLoaded |
+          lldb::SBTarget::eBroadcastBitSymbolsChanged |
+          lldb::SBTarget::eBroadcastBitNewTargetCreated);
 
   // Create a new event thread and store it.
   auto new_thread_sp = std::make_shared<ManagedEventThread>(
@@ -137,7 +146,18 @@ DAP *DAPSessionManager::FindDAPForTarget(lldb::SBTarget target) {
     if (dap && dap->target.IsValid() && dap->target == target)
       return dap;
 
-  return nullptr;
+  // Fallback for events that fire before SetTarget binds the target.
+  // Route to the unique DAP for this target's debugger if there is one.
+  const lldb::user_id_t debugger_id = target.GetDebugger().GetID();
+  DAP *unique_dap = nullptr;
+  for (const auto &[loop, dap] : m_active_sessions) {
+    if (!dap || dap->debugger.GetID() != debugger_id)
+      continue;
+    if (unique_dap)
+      return nullptr;
+    unique_dap = dap;
+  }
+  return unique_dap;
 }
 
 void DAPSessionManager::ReleaseExpiredEventThreads() {
diff --git a/lldb/tools/lldb-dap/EventHelper.cpp b/lldb/tools/lldb-dap/EventHelper.cpp
index e9f64d8e72d08..2e0f71d69db65 100644
--- a/lldb/tools/lldb-dap/EventHelper.cpp
+++ b/lldb/tools/lldb-dap/EventHelper.cpp
@@ -475,7 +475,7 @@ static void HandleTargetEvent(const lldb::SBEvent &event, Log &log) {
 
     // NOTE: Both mutexes must be acquired to prevent deadlock when
     // handling `modules_request`, which also requires both locks.
-    lldb::SBMutex api_mutex = dap->GetAPIMutex();
+    lldb::SBMutex api_mutex = target.GetAPIMutex();
     const std::scoped_lock<lldb::SBMutex, std::mutex> guard(api_mutex,
                                                             dap->modules_mutex);
     for (uint32_t i = 0; i < num_modules; ++i) {
@@ -483,7 +483,7 @@ static void HandleTargetEvent(const lldb::SBEvent &event, Log &log) {
           lldb::SBTarget::GetModuleAtIndexFromEvent(i, event);
 
       std::optional<protocol::Module> p_module =
-          CreateModule(dap->target, module, remove_module);
+          CreateModule(target, module, remove_module);
       if (!p_module)
         continue;
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/201866


More information about the lldb-commits mailing list