@@ -1319,7 +1319,7 @@ void DAP::ProgressEventThread() {
13191319 lldb::SBEvent event;
13201320 bool done = false ;
13211321 while (!done) {
1322- if (listener.WaitForEvent (1 , event)) {
1322+ if (listener.WaitForEvent (UINT32_MAX , event)) {
13231323 const auto event_mask = event.GetType ();
13241324 if (event.BroadcasterMatchesRef (broadcaster)) {
13251325 if (event_mask & eBroadcastBitStopProgressThread) {
@@ -1377,7 +1377,6 @@ void DAP::ProgressEventThread() {
13771377// is required.
13781378void DAP::EventThread () {
13791379 llvm::set_thread_name (" lldb.DAP.client." + m_client_name + " .event_handler" );
1380- lldb::SBEvent event;
13811380 lldb::SBListener listener = debugger.GetListener ();
13821381 broadcaster.AddListener (listener, eBroadcastBitStopEventThread);
13831382 debugger.GetBroadcaster ().AddListener (
@@ -1388,169 +1387,176 @@ void DAP::EventThread() {
13881387 debugger, lldb::SBThread::GetBroadcasterClassName (),
13891388 lldb::SBThread::eBroadcastBitStackChanged);
13901389
1390+ lldb::SBEvent event;
13911391 bool done = false ;
13921392 while (!done) {
1393- if (listener.WaitForEvent (1 , event)) {
1394- const auto event_mask = event.GetType ();
1395- if (lldb::SBProcess::EventIsProcessEvent (event)) {
1396- lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent (event);
1397- if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
1398- auto state = lldb::SBProcess::GetStateFromEvent (event);
1399- switch (state) {
1400- case lldb::eStateConnected:
1401- case lldb::eStateDetached:
1402- case lldb::eStateInvalid:
1403- case lldb::eStateUnloaded:
1404- break ;
1405- case lldb::eStateAttaching:
1406- case lldb::eStateCrashed:
1407- case lldb::eStateLaunching:
1408- case lldb::eStateStopped:
1409- case lldb::eStateSuspended:
1410- // Only report a stopped event if the process was not
1411- // automatically restarted.
1412- if (!lldb::SBProcess::GetRestartedFromEvent (event)) {
1413- SendStdOutStdErr (*this , process);
1414- if (llvm::Error err = SendThreadStoppedEvent (*this ))
1415- DAP_LOG_ERROR (log, std::move (err),
1416- " ({1}) reporting thread stopped: {0}" ,
1417- m_client_name);
1418- }
1419- break ;
1420- case lldb::eStateRunning:
1421- case lldb::eStateStepping:
1422- WillContinue ();
1423- SendContinuedEvent (*this );
1424- break ;
1425- case lldb::eStateExited:
1426- lldb::SBStream stream;
1427- process.GetStatus (stream);
1428- SendOutput (OutputType::Console, stream.GetData ());
1429-
1430- // When restarting, we can get an "exited" event for the process we
1431- // just killed with the old PID, or even with no PID. In that case
1432- // we don't have to terminate the session.
1433- if (process.GetProcessID () == LLDB_INVALID_PROCESS_ID ||
1434- process.GetProcessID () == restarting_process_id) {
1435- restarting_process_id = LLDB_INVALID_PROCESS_ID;
1436- } else {
1437- // Run any exit LLDB commands the user specified in the
1438- // launch.json
1439- RunExitCommands ();
1440- SendProcessExitedEvent (*this , process);
1441- SendTerminatedEvent ();
1442- done = true ;
1443- }
1444- break ;
1445- }
1446- } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
1447- (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
1448- SendStdOutStdErr (*this , process);
1449- }
1450- } else if (lldb::SBTarget::EventIsTargetEvent (event)) {
1451- if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
1452- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
1453- event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded ||
1454- event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged) {
1455- const uint32_t num_modules =
1456- lldb::SBTarget::GetNumModulesFromEvent (event);
1457- const bool remove_module =
1458- event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded;
1459-
1460- // NOTE: Both mutexes must be acquired to prevent deadlock when
1461- // handling `modules_request`, which also requires both locks.
1462- lldb::SBMutex api_mutex = GetAPIMutex ();
1463- const std::scoped_lock<lldb::SBMutex, std::mutex> guard (
1464- api_mutex, modules_mutex);
1465- for (uint32_t i = 0 ; i < num_modules; ++i) {
1466- lldb::SBModule module =
1467- lldb::SBTarget::GetModuleAtIndexFromEvent (i, event);
1468-
1469- std::optional<protocol::Module> p_module =
1470- CreateModule (target, module , remove_module);
1471- if (!p_module)
1472- continue ;
1473-
1474- llvm::StringRef module_id = p_module->id ;
1475-
1476- const bool module_exists = modules.contains (module_id);
1477- if (remove_module && module_exists) {
1478- modules.erase (module_id);
1479- Send (protocol::Event{
1480- " module" , ModuleEventBody{std::move (p_module).value (),
1481- ModuleEventBody::eReasonRemoved}});
1482- } else if (module_exists) {
1483- Send (protocol::Event{
1484- " module" , ModuleEventBody{std::move (p_module).value (),
1485- ModuleEventBody::eReasonChanged}});
1486- } else if (!remove_module) {
1487- modules.insert (module_id);
1488- Send (protocol::Event{
1489- " module" , ModuleEventBody{std::move (p_module).value (),
1490- ModuleEventBody::eReasonNew}});
1491- }
1492- }
1493- }
1494- } else if (lldb::SBBreakpoint::EventIsBreakpointEvent (event)) {
1495- if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
1496- auto event_type =
1497- lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
1498- auto bp = Breakpoint (
1499- *this , lldb::SBBreakpoint::GetBreakpointFromEvent (event));
1500- // If the breakpoint was set through DAP, it will have the
1501- // BreakpointBase::kDAPBreakpointLabel. Regardless of whether
1502- // locations were added, removed, or resolved, the breakpoint isn't
1503- // going away and the reason is always "changed".
1504- if ((event_type & lldb::eBreakpointEventTypeLocationsAdded ||
1505- event_type & lldb::eBreakpointEventTypeLocationsRemoved ||
1506- event_type & lldb::eBreakpointEventTypeLocationsResolved) &&
1507- bp.MatchesName (BreakpointBase::kDAPBreakpointLabel )) {
1508- // As the DAP client already knows the path of this breakpoint, we
1509- // don't need to send it back as part of the "changed" event. This
1510- // avoids sending paths that should be source mapped. Note that
1511- // CreateBreakpoint doesn't apply source mapping and certain
1512- // implementation ignore the source part of this event anyway.
1513- protocol::Breakpoint protocol_bp = bp.ToProtocolBreakpoint ();
1514-
1515- // "source" is not needed here, unless we add adapter data to be
1516- // saved by the client.
1517- if (protocol_bp.source && !protocol_bp.source ->adapterData )
1518- protocol_bp.source = std::nullopt ;
1519-
1520- llvm::json::Object body;
1521- body.try_emplace (" breakpoint" , protocol_bp);
1522- body.try_emplace (" reason" , " changed" );
1523-
1524- llvm::json::Object bp_event = CreateEventObject (" breakpoint" );
1525- bp_event.try_emplace (" body" , std::move (body));
1526-
1527- SendJSON (llvm::json::Value (std::move (bp_event)));
1528- }
1529- }
1393+ if (!listener.WaitForEvent (UINT32_MAX, event))
1394+ continue ;
15301395
1531- } else if (lldb::SBThread::EventIsThreadEvent (event)) {
1532- HandleThreadEvent (event);
1533- } else if (event_mask & lldb::eBroadcastBitError ||
1534- event_mask & lldb::eBroadcastBitWarning) {
1535- lldb::SBStructuredData data =
1536- lldb::SBDebugger::GetDiagnosticFromEvent (event);
1537- if (!data.IsValid ())
1538- continue ;
1539- std::string type = GetStringValue (data.GetValueForKey (" type" ));
1540- std::string message = GetStringValue (data.GetValueForKey (" message" ));
1541- SendOutput (OutputType::Important,
1542- llvm::formatv (" {0}: {1}" , type, message).str ());
1543- } else if (event.BroadcasterMatchesRef (broadcaster)) {
1544- if (event_mask & eBroadcastBitStopEventThread) {
1545- done = true ;
1546- }
1396+ const uint32_t event_mask = event.GetType ();
1397+ if (lldb::SBProcess::EventIsProcessEvent (event)) {
1398+ HandleProcessEvent (event, /* &process_exited=*/ done);
1399+ } else if (lldb::SBTarget::EventIsTargetEvent (event)) {
1400+ HandleTargetEvent (event);
1401+ } else if (lldb::SBBreakpoint::EventIsBreakpointEvent (event)) {
1402+ HandleBreakpointEvent (event);
1403+ } else if (lldb::SBThread::EventIsThreadEvent (event)) {
1404+ HandleThreadEvent (event);
1405+ } else if (event_mask & lldb::eBroadcastBitError ||
1406+ event_mask & lldb::eBroadcastBitWarning) {
1407+ HandleDiagnosticEvent (event);
1408+ } else if (event.BroadcasterMatchesRef (broadcaster)) {
1409+ if (event_mask & eBroadcastBitStopEventThread) {
1410+ done = true ;
1411+ }
1412+ }
1413+ }
1414+ }
1415+
1416+ void DAP::HandleProcessEvent (const lldb::SBEvent &event, bool &process_exited) {
1417+ lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent (event);
1418+ const uint32_t event_mask = event.GetType ();
1419+ if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
1420+ auto state = lldb::SBProcess::GetStateFromEvent (event);
1421+ switch (state) {
1422+ case lldb::eStateConnected:
1423+ case lldb::eStateDetached:
1424+ case lldb::eStateInvalid:
1425+ case lldb::eStateUnloaded:
1426+ break ;
1427+ case lldb::eStateAttaching:
1428+ case lldb::eStateCrashed:
1429+ case lldb::eStateLaunching:
1430+ case lldb::eStateStopped:
1431+ case lldb::eStateSuspended:
1432+ // Only report a stopped event if the process was not
1433+ // automatically restarted.
1434+ if (!lldb::SBProcess::GetRestartedFromEvent (event)) {
1435+ SendStdOutStdErr (*this , process);
1436+ if (llvm::Error err = SendThreadStoppedEvent (*this ))
1437+ DAP_LOG_ERROR (log, std::move (err),
1438+ " ({1}) reporting thread stopped: {0}" , m_client_name);
1439+ }
1440+ break ;
1441+ case lldb::eStateRunning:
1442+ case lldb::eStateStepping:
1443+ WillContinue ();
1444+ SendContinuedEvent (*this );
1445+ break ;
1446+ case lldb::eStateExited:
1447+ lldb::SBStream stream;
1448+ process.GetStatus (stream);
1449+ SendOutput (OutputType::Console, stream.GetData ());
1450+
1451+ // When restarting, we can get an "exited" event for the process we
1452+ // just killed with the old PID, or even with no PID. In that case
1453+ // we don't have to terminate the session.
1454+ if (process.GetProcessID () == LLDB_INVALID_PROCESS_ID ||
1455+ process.GetProcessID () == restarting_process_id) {
1456+ restarting_process_id = LLDB_INVALID_PROCESS_ID;
1457+ } else {
1458+ // Run any exit LLDB commands the user specified in the
1459+ // launch.json
1460+ RunExitCommands ();
1461+ SendProcessExitedEvent (*this , process);
1462+ SendTerminatedEvent ();
1463+ process_exited = true ;
1464+ }
1465+ break ;
1466+ }
1467+ } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
1468+ (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
1469+ SendStdOutStdErr (*this , process);
1470+ }
1471+ }
1472+
1473+ void DAP::HandleTargetEvent (const lldb::SBEvent &event) {
1474+ const uint32_t event_mask = event.GetType ();
1475+ if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
1476+ event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
1477+ event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded ||
1478+ event_mask & lldb::SBTarget::eBroadcastBitSymbolsChanged) {
1479+ const uint32_t num_modules = lldb::SBTarget::GetNumModulesFromEvent (event);
1480+ const bool remove_module =
1481+ event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded;
1482+
1483+ // NOTE: Both mutexes must be acquired to prevent deadlock when
1484+ // handling `modules_request`, which also requires both locks.
1485+ lldb::SBMutex api_mutex = GetAPIMutex ();
1486+ const std::scoped_lock<lldb::SBMutex, std::mutex> guard (api_mutex,
1487+ modules_mutex);
1488+ for (uint32_t i = 0 ; i < num_modules; ++i) {
1489+ lldb::SBModule module =
1490+ lldb::SBTarget::GetModuleAtIndexFromEvent (i, event);
1491+
1492+ std::optional<protocol::Module> p_module =
1493+ CreateModule (target, module , remove_module);
1494+ if (!p_module)
1495+ continue ;
1496+
1497+ const llvm::StringRef module_id = p_module->id ;
1498+
1499+ const bool module_exists = modules.contains (module_id);
1500+ if (remove_module && module_exists) {
1501+ modules.erase (module_id);
1502+ Send (protocol::Event{" module" ,
1503+ ModuleEventBody{std::move (p_module).value (),
1504+ ModuleEventBody::eReasonRemoved}});
1505+ } else if (module_exists) {
1506+ Send (protocol::Event{" module" ,
1507+ ModuleEventBody{std::move (p_module).value (),
1508+ ModuleEventBody::eReasonChanged}});
1509+ } else if (!remove_module) {
1510+ modules.insert (module_id);
1511+ Send (protocol::Event{" module" ,
1512+ ModuleEventBody{std::move (p_module).value (),
1513+ ModuleEventBody::eReasonNew}});
15471514 }
15481515 }
15491516 }
15501517}
15511518
1519+ void DAP::HandleBreakpointEvent (const lldb::SBEvent &event) {
1520+ const uint32_t event_mask = event.GetType ();
1521+ if (!(event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged))
1522+ return ;
1523+
1524+ auto event_type = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
1525+ auto bp =
1526+ Breakpoint (*this , lldb::SBBreakpoint::GetBreakpointFromEvent (event));
1527+ // If the breakpoint was set through DAP, it will have the
1528+ // BreakpointBase::kDAPBreakpointLabel. Regardless of whether
1529+ // locations were added, removed, or resolved, the breakpoint isn't
1530+ // going away and the reason is always "changed".
1531+ if ((event_type & lldb::eBreakpointEventTypeLocationsAdded ||
1532+ event_type & lldb::eBreakpointEventTypeLocationsRemoved ||
1533+ event_type & lldb::eBreakpointEventTypeLocationsResolved) &&
1534+ bp.MatchesName (BreakpointBase::kDAPBreakpointLabel )) {
1535+ // As the DAP client already knows the path of this breakpoint, we
1536+ // don't need to send it back as part of the "changed" event. This
1537+ // avoids sending paths that should be source mapped. Note that
1538+ // CreateBreakpoint doesn't apply source mapping and certain
1539+ // implementation ignore the source part of this event anyway.
1540+ protocol::Breakpoint protocol_bp = bp.ToProtocolBreakpoint ();
1541+
1542+ // "source" is not needed here, unless we add adapter data to be
1543+ // saved by the client.
1544+ if (protocol_bp.source && !protocol_bp.source ->adapterData )
1545+ protocol_bp.source = std::nullopt ;
1546+
1547+ llvm::json::Object body;
1548+ body.try_emplace (" breakpoint" , protocol_bp);
1549+ body.try_emplace (" reason" , " changed" );
1550+
1551+ llvm::json::Object bp_event = CreateEventObject (" breakpoint" );
1552+ bp_event.try_emplace (" body" , std::move (body));
1553+
1554+ SendJSON (llvm::json::Value (std::move (bp_event)));
1555+ }
1556+ }
1557+
15521558void DAP::HandleThreadEvent (const lldb::SBEvent &event) {
1553- uint32_t event_type = event.GetType ();
1559+ const uint32_t event_type = event.GetType ();
15541560
15551561 if (event_type & lldb::SBThread::eBroadcastBitStackChanged) {
15561562 const lldb::SBThread evt_thread = lldb::SBThread::GetThreadFromEvent (event);
@@ -1559,6 +1565,18 @@ void DAP::HandleThreadEvent(const lldb::SBEvent &event) {
15591565 }
15601566}
15611567
1568+ void DAP::HandleDiagnosticEvent (const lldb::SBEvent &event) {
1569+ const lldb::SBStructuredData data =
1570+ lldb::SBDebugger::GetDiagnosticFromEvent (event);
1571+ if (!data.IsValid ())
1572+ return ;
1573+
1574+ std::string type = GetStringValue (data.GetValueForKey (" type" ));
1575+ std::string message = GetStringValue (data.GetValueForKey (" message" ));
1576+ SendOutput (OutputType::Important,
1577+ llvm::formatv (" {0}: {1}" , type, message).str ());
1578+ }
1579+
15621580std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints (
15631581 const protocol::Source &source,
15641582 const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints) {
0 commit comments