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