Skip to content

Commit d0a0878

Browse files
committed
[lldb-dap] Refactor event thread
Handle each event type in a different function
1 parent d78e0de commit d0a0878

File tree

2 files changed

+178
-156
lines changed

2 files changed

+178
-156
lines changed

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 174 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
13761376
void 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+
15501556
void 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+
15601578
std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints(
15611579
const protocol::Source &source,
15621580
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints) {

lldb/tools/lldb-dap/DAP.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,11 @@ struct DAP final : public DAPTransport::MessageHandler {
454454
/// Event threads.
455455
/// @{
456456
void EventThread();
457+
void HandleProcessEvent(const lldb::SBEvent &event, bool &process_exited);
458+
void HandleTargetEvent(const lldb::SBEvent &event);
459+
void HandleBreakpointEvent(const lldb::SBEvent &event);
457460
void HandleThreadEvent(const lldb::SBEvent &event);
461+
void HandleDiagnosticEvent(const lldb::SBEvent &event);
458462
void ProgressEventThread();
459463

460464
std::thread event_thread;

0 commit comments

Comments
 (0)