brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · d5440ff Raw
143 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "DAPSessionManager.h"9#include "DAP.h"10#include "EventHelper.h"11#include "lldb/API/SBBroadcaster.h"12#include "lldb/API/SBEvent.h"13#include "lldb/API/SBTarget.h"14#include "lldb/Host/MainLoopBase.h"15#include "llvm/Support/Threading.h"16#include "llvm/Support/WithColor.h"17 18#include <chrono>19#include <mutex>20 21namespace lldb_dap {22 23ManagedEventThread::ManagedEventThread(lldb::SBBroadcaster broadcaster,24                                       std::thread t)25    : m_broadcaster(broadcaster), m_event_thread(std::move(t)) {}26 27ManagedEventThread::~ManagedEventThread() {28  if (m_event_thread.joinable()) {29    m_broadcaster.BroadcastEventByType(eBroadcastBitStopEventThread);30    m_event_thread.join();31  }32}33 34DAPSessionManager &DAPSessionManager::GetInstance() {35  static std::once_flag initialized;36  static DAPSessionManager *instance =37      nullptr; // NOTE: intentional leak to avoid issues with C++ destructor38               // chain39 40  std::call_once(initialized, []() { instance = new DAPSessionManager(); });41 42  return *instance;43}44 45void DAPSessionManager::RegisterSession(lldb_private::MainLoop *loop,46                                        DAP *dap) {47  std::lock_guard<std::mutex> lock(m_sessions_mutex);48  m_active_sessions[loop] = dap;49}50 51void DAPSessionManager::UnregisterSession(lldb_private::MainLoop *loop) {52  std::unique_lock<std::mutex> lock(m_sessions_mutex);53  m_active_sessions.erase(loop);54  std::notify_all_at_thread_exit(m_sessions_condition, std::move(lock));55}56 57std::vector<DAP *> DAPSessionManager::GetActiveSessions() {58  std::lock_guard<std::mutex> lock(m_sessions_mutex);59  std::vector<DAP *> sessions;60  for (const auto &[loop, dap] : m_active_sessions)61    if (dap)62      sessions.emplace_back(dap);63  return sessions;64}65 66void DAPSessionManager::DisconnectAllSessions() {67  std::lock_guard<std::mutex> lock(m_sessions_mutex);68  m_client_failed = false;69  for (auto [loop, dap] : m_active_sessions) {70    if (dap) {71      if (llvm::Error error = dap->Disconnect()) {72        m_client_failed = true;73        llvm::WithColor::error() << "DAP client disconnected failed: "74                                 << llvm::toString(std::move(error)) << "\n";75      }76      loop->AddPendingCallback(77          [](lldb_private::MainLoopBase &loop) { loop.RequestTermination(); });78    }79  }80}81 82llvm::Error DAPSessionManager::WaitForAllSessionsToDisconnect() {83  std::unique_lock<std::mutex> lock(m_sessions_mutex);84  m_sessions_condition.wait(lock, [this] { return m_active_sessions.empty(); });85 86  // Check if any disconnection failed and return appropriate error.87  if (m_client_failed)88    return llvm::make_error<llvm::StringError>(89        "disconnecting all clients failed", llvm::inconvertibleErrorCode());90 91  return llvm::Error::success();92}93 94std::shared_ptr<ManagedEventThread>95DAPSessionManager::GetEventThreadForDebugger(lldb::SBDebugger debugger,96                                             DAP *requesting_dap) {97  lldb::user_id_t debugger_id = debugger.GetID();98  std::lock_guard<std::mutex> lock(m_sessions_mutex);99 100  // Try to use shared event thread, if it exists.101  if (auto it = m_debugger_event_threads.find(debugger_id);102      it != m_debugger_event_threads.end()) {103    if (std::shared_ptr<ManagedEventThread> thread_sp = it->second.lock())104      return thread_sp;105    // Our weak pointer has expired.106    m_debugger_event_threads.erase(it);107  }108 109  // Create a new event thread and store it.110  auto new_thread_sp = std::make_shared<ManagedEventThread>(111      requesting_dap->broadcaster,112      std::thread(EventThread, debugger, requesting_dap->broadcaster,113                  requesting_dap->m_client_name, requesting_dap->log));114  m_debugger_event_threads[debugger_id] = new_thread_sp;115  return new_thread_sp;116}117 118DAP *DAPSessionManager::FindDAPForTarget(lldb::SBTarget target) {119  std::lock_guard<std::mutex> lock(m_sessions_mutex);120 121  for (const auto &[loop, dap] : m_active_sessions)122    if (dap && dap->target.IsValid() && dap->target == target)123      return dap;124 125  return nullptr;126}127 128void DAPSessionManager::ReleaseExpiredEventThreads() {129  std::lock_guard<std::mutex> lock(m_sessions_mutex);130  for (auto it = m_debugger_event_threads.begin();131       it != m_debugger_event_threads.end();) {132    // Check if the weak_ptr has expired (no DAP instances are using it133    // anymore).134    if (it->second.expired()) {135      it = m_debugger_event_threads.erase(it);136    } else {137      ++it;138    }139  }140}141 142} // namespace lldb_dap143