@@ -1467,260 +1467,6 @@ void DAP::ProgressEventThread() {
14671467 }
14681468}
14691469
1470- // All events from the debugger, target, process, thread and frames are
1471- // received in this function that runs in its own thread. We are using a
1472- // "FILE *" to output packets back to VS Code and they have mutexes in them
1473- // them prevent multiple threads from writing simultaneously so no locking
1474- // is required.
1475- void DAP::EventThread () {
1476- llvm::set_thread_name (" lldb.DAP.client." + m_client_name + " .event_handler" );
1477- lldb::SBEvent event;
1478- lldb::SBListener listener = debugger.GetListener ();
1479- broadcaster.AddListener (listener, eBroadcastBitStopEventThread);
1480- debugger.GetBroadcaster ().AddListener (
1481- listener, lldb::eBroadcastBitError | lldb::eBroadcastBitWarning);
1482-
1483- // listen for thread events.
1484- listener.StartListeningForEventClass (
1485- debugger, lldb::SBThread::GetBroadcasterClassName (),
1486- lldb::SBThread::eBroadcastBitStackChanged);
1487-
1488- bool done = false ;
1489- while (!done) {
1490- if (listener.WaitForEvent (1 , event)) {
1491- const auto event_mask = event.GetType ();
1492- if (lldb::SBProcess::EventIsProcessEvent (event)) {
1493- lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent (event);
1494- // Find the DAP instance that owns this process's target.
1495- DAP *dap_instance = DAPSessionManager::FindDAP (process.GetTarget ());
1496- if (!dap_instance) {
1497- DAP_LOG (log, " Unable to find DAP instance for process {0}" ,
1498- process.GetProcessID ());
1499- continue ;
1500- }
1501-
1502- if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
1503- auto state = lldb::SBProcess::GetStateFromEvent (event);
1504- switch (state) {
1505- case lldb::eStateConnected:
1506- case lldb::eStateDetached:
1507- case lldb::eStateInvalid:
1508- case lldb::eStateUnloaded:
1509- break ;
1510- case lldb::eStateAttaching:
1511- case lldb::eStateCrashed:
1512- case lldb::eStateLaunching:
1513- case lldb::eStateStopped:
1514- case lldb::eStateSuspended:
1515- // Only report a stopped event if the process was not
1516- // automatically restarted.
1517- if (!lldb::SBProcess::GetRestartedFromEvent (event)) {
1518- SendStdOutStdErr (*dap_instance, process);
1519- if (llvm::Error err = SendThreadStoppedEvent (*dap_instance))
1520- DAP_LOG_ERROR (dap_instance->log , std::move (err),
1521- " ({1}) reporting thread stopped: {0}" ,
1522- dap_instance->m_client_name );
1523- }
1524- break ;
1525- case lldb::eStateRunning:
1526- case lldb::eStateStepping:
1527- dap_instance->WillContinue ();
1528- SendContinuedEvent (*dap_instance);
1529- break ;
1530- case lldb::eStateExited:
1531- lldb::SBStream stream;
1532- process.GetStatus (stream);
1533- dap_instance->SendOutput (OutputType::Console, stream.GetData ());
1534-
1535- // When restarting, we can get an "exited" event for the process we
1536- // just killed with the old PID, or even with no PID. In that case
1537- // we don't have to terminate the session.
1538- if (process.GetProcessID () == LLDB_INVALID_PROCESS_ID ||
1539- process.GetProcessID () == dap_instance->restarting_process_id ) {
1540- dap_instance->restarting_process_id = LLDB_INVALID_PROCESS_ID;
1541- } else {
1542- // Run any exit LLDB commands the user specified in the
1543- // launch.json
1544- dap_instance->RunExitCommands ();
1545- SendProcessExitedEvent (*dap_instance, process);
1546- dap_instance->SendTerminatedEvent ();
1547- done = true ;
1548- }
1549- break ;
1550- }
1551- } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
1552- (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
1553- SendStdOutStdErr (*dap_instance, process);
1554- }
1555- } else if (lldb::SBTarget::EventIsTargetEvent (event)) {
1556- if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
1557- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
1558- event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded ||
1559- event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged) {
1560- lldb::SBTarget event_target =
1561- lldb::SBTarget::GetTargetFromEvent (event);
1562- // Find the DAP instance that owns this target.
1563- DAP *dap_instance = DAPSessionManager::FindDAP (event_target);
1564- if (!dap_instance)
1565- continue ;
1566-
1567- const uint32_t num_modules =
1568- lldb::SBTarget::GetNumModulesFromEvent (event);
1569- const bool remove_module =
1570- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded;
1571-
1572- // NOTE: Both mutexes must be acquired to prevent deadlock when
1573- // handling `modules_request`, which also requires both locks.
1574- lldb::SBMutex api_mutex = GetAPIMutex ();
1575- const std::scoped_lock<lldb::SBMutex, std::mutex> guard (
1576- api_mutex, dap_instance->modules_mutex );
1577- for (uint32_t i = 0 ; i < num_modules; ++i) {
1578- lldb::SBModule module =
1579- lldb::SBTarget::GetModuleAtIndexFromEvent (i, event);
1580-
1581- std::optional<protocol::Module> p_module =
1582- CreateModule (dap_instance->target , module , remove_module);
1583- if (!p_module)
1584- continue ;
1585-
1586- llvm::StringRef module_id = p_module->id ;
1587-
1588- const bool module_exists =
1589- dap_instance->modules .contains (module_id);
1590- if (remove_module && module_exists) {
1591- dap_instance->modules .erase (module_id);
1592- dap_instance->Send (protocol::Event{
1593- " module" , ModuleEventBody{std::move (p_module).value (),
1594- ModuleEventBody::eReasonRemoved}});
1595- } else if (module_exists) {
1596- dap_instance->Send (protocol::Event{
1597- " module" , ModuleEventBody{std::move (p_module).value (),
1598- ModuleEventBody::eReasonChanged}});
1599- } else if (!remove_module) {
1600- dap_instance->modules .insert (module_id);
1601- dap_instance->Send (protocol::Event{
1602- " module" , ModuleEventBody{std::move (p_module).value (),
1603- ModuleEventBody::eReasonNew}});
1604- }
1605- }
1606- } else if (event_mask & lldb::SBTarget::eBroadcastBitNewTargetCreated) {
1607- auto target = lldb::SBTarget::GetTargetFromEvent (event);
1608-
1609- lldb::user_id_t target_id = target.GetGloballyUniqueID ();
1610- lldb::SBDebugger target_debugger = target.GetDebugger ();
1611- int debugger_id = target_debugger.GetID ();
1612-
1613- // We create an attach config that contains the debugger ID and target
1614- // ID. The new DAP instance will use these IDs to find the existing
1615- // debugger and target via FindDebuggerWithID and
1616- // FindTargetByGloballyUniqueID.
1617- llvm::json::Object attach_config;
1618-
1619- attach_config.try_emplace (" type" , " lldb" );
1620- attach_config.try_emplace (" debuggerId" , debugger_id);
1621- attach_config.try_emplace (" targetId" , target_id);
1622- const char *session_name = target.GetTargetSessionName ();
1623- attach_config.try_emplace (" name" , session_name);
1624-
1625- // 2. Construct the main 'startDebugging' request arguments.
1626- llvm::json::Object start_debugging_args{
1627- {" request" , " attach" },
1628- {" configuration" , std::move (attach_config)}};
1629-
1630- // Send the request. Note that this is a reverse request, so you don't
1631- // expect a direct response in the same way as a client request.
1632- SendReverseRequest<LogFailureResponseHandler>(
1633- " startDebugging" , std::move (start_debugging_args));
1634- }
1635- } else if (lldb::SBBreakpoint::EventIsBreakpointEvent (event)) {
1636- lldb::SBBreakpoint bp =
1637- lldb::SBBreakpoint::GetBreakpointFromEvent (event);
1638- if (!bp.IsValid ())
1639- continue ;
1640-
1641- lldb::SBTarget event_target = bp.GetTarget ();
1642-
1643- // Find the DAP instance that owns this target.
1644- DAP *dap_instance = DAPSessionManager::FindDAP (event_target);
1645- if (!dap_instance)
1646- continue ;
1647-
1648- if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
1649- auto event_type =
1650- lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
1651- auto breakpoint = Breakpoint (*dap_instance, bp);
1652- // If the breakpoint was set through DAP, it will have the
1653- // BreakpointBase::kDAPBreakpointLabel. Regardless of whether
1654- // locations were added, removed, or resolved, the breakpoint isn't
1655- // going away and the reason is always "changed".
1656- if ((event_type & lldb::eBreakpointEventTypeLocationsAdded ||
1657- event_type & lldb::eBreakpointEventTypeLocationsRemoved ||
1658- event_type & lldb::eBreakpointEventTypeLocationsResolved) &&
1659- breakpoint.MatchesName (BreakpointBase::kDAPBreakpointLabel )) {
1660- // As the DAP client already knows the path of this breakpoint, we
1661- // don't need to send it back as part of the "changed" event. This
1662- // avoids sending paths that should be source mapped. Note that
1663- // CreateBreakpoint doesn't apply source mapping and certain
1664- // implementation ignore the source part of this event anyway.
1665- protocol::Breakpoint protocol_bp =
1666- breakpoint.ToProtocolBreakpoint ();
1667- // "source" is not needed here, unless we add adapter data to be
1668- // saved by the client.
1669- if (protocol_bp.source && !protocol_bp.source ->adapterData )
1670- protocol_bp.source = std::nullopt ;
1671-
1672- llvm::json::Object body;
1673- body.try_emplace (" breakpoint" , protocol_bp);
1674- body.try_emplace (" reason" , " changed" );
1675-
1676- llvm::json::Object bp_event = CreateEventObject (" breakpoint" );
1677- bp_event.try_emplace (" body" , std::move (body));
1678-
1679- dap_instance->SendJSON (llvm::json::Value (std::move (bp_event)));
1680- }
1681- }
1682-
1683- } else if (lldb::SBThread::EventIsThreadEvent (event)) {
1684- HandleThreadEvent (event);
1685- } else if (event_mask & lldb::eBroadcastBitError ||
1686- event_mask & lldb::eBroadcastBitWarning) {
1687- // Global debugger events - send to all DAP instances.
1688- std::vector<DAP *> active_instances =
1689- DAPSessionManager::GetInstance ().GetActiveSessions ();
1690- for (DAP *dap_instance : active_instances) {
1691- if (!dap_instance)
1692- continue ;
1693-
1694- lldb::SBStructuredData data =
1695- lldb::SBDebugger::GetDiagnosticFromEvent (event);
1696- if (!data.IsValid ())
1697- continue ;
1698-
1699- std::string type = GetStringValue (data.GetValueForKey (" type" ));
1700- std::string message = GetStringValue (data.GetValueForKey (" message" ));
1701- dap_instance->SendOutput (
1702- OutputType::Important,
1703- llvm::formatv (" {0}: {1}" , type, message).str ());
1704- }
1705- } else if (event.BroadcasterMatchesRef (broadcaster)) {
1706- if (event_mask & eBroadcastBitStopEventThread) {
1707- done = true ;
1708- }
1709- }
1710- }
1711- }
1712- }
1713-
1714- void DAP::HandleThreadEvent (const lldb::SBEvent &event) {
1715- uint32_t event_type = event.GetType ();
1716-
1717- if (event_type & lldb::SBThread::eBroadcastBitStackChanged) {
1718- const lldb::SBThread evt_thread = lldb::SBThread::GetThreadFromEvent (event);
1719- SendInvalidatedEvent (*this , {InvalidatedEventBody::eAreaStacks},
1720- evt_thread.GetThreadID ());
1721- }
1722- }
1723-
17241470std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints (
17251471 const protocol::Source &source,
17261472 const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints) {
0 commit comments