https://github.com/charles-zablit created https://github.com/llvm/llvm-project/pull/201866
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. >From 3fd10b982084b9e5a6ca7a292a7cafc66e7894d2 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Fri, 5 Jun 2026 16:39:11 +0100 Subject: [PATCH] [lldb-dap] subscribe to target events at the broadcaster-manager level --- .../attach-commands/TestDAP_attachCommands.py | 1 - .../TestDAP_launch_extra_launch_commands.py | 3 +-- lldb/tools/lldb-dap/DAP.cpp | 19 +--------------- lldb/tools/lldb-dap/DAPSessionManager.cpp | 22 ++++++++++++++++++- lldb/tools/lldb-dap/EventHelper.cpp | 4 ++-- 5 files changed, 25 insertions(+), 24 deletions(-) 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; _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
