Debugger: Fix threads request segfault after thread exited event

Fixes: #25041
stage/master/nightly/2023/06/30^2
Ben McMorran 2023-06-29 09:10:46 -07:00 committed by Brad King
parent 7952e11466
commit 764258771a
2 changed files with 39 additions and 5 deletions

View File

@ -167,10 +167,16 @@ cmDebuggerAdapter::cmDebuggerAdapter(
(void)req;
std::unique_lock<std::mutex> lock(Mutex);
dap::ThreadsResponse response;
dap::Thread thread;
thread.id = DefaultThread->GetId();
thread.name = DefaultThread->GetName();
response.threads.push_back(thread);
// If a client requests threads during shutdown (like after receiving the
// thread exited event), DefaultThread won't be set.
if (DefaultThread) {
dap::Thread thread;
thread.id = DefaultThread->GetId();
thread.name = DefaultThread->GetName();
response.threads.push_back(thread);
}
return response;
});

View File

@ -53,7 +53,7 @@ public:
std::shared_ptr<dap::ReaderWriter> DebuggerToClient;
};
bool testBasicProtocol()
bool runTest(std::function<bool(dap::Session&)> onThreadExitedEvent)
{
std::promise<bool> debuggerAdapterInitializedPromise;
std::future<bool> debuggerAdapterInitializedFuture =
@ -152,6 +152,11 @@ bool testBasicProtocol()
std::future_status::ready);
ASSERT_TRUE(threadExitedFuture.wait_for(futureTimeout) ==
std::future_status::ready);
if (onThreadExitedEvent) {
ASSERT_TRUE(onThreadExitedEvent(*client));
}
ASSERT_TRUE(exitedEventReceivedFuture.wait_for(futureTimeout) ==
std::future_status::ready);
ASSERT_TRUE(terminatedEventReceivedFuture.wait_for(futureTimeout) ==
@ -165,9 +170,32 @@ bool testBasicProtocol()
return true;
}
bool testBasicProtocol()
{
return runTest(nullptr);
}
bool testThreadsRequestAfterThreadExitedEvent()
{
return runTest([](dap::Session& session) -> bool {
// Try requesting threads again after receiving the thread exited event.
// Some clients do this to ensure that their thread list is up-to-date.
dap::ThreadsRequest threadsRequest;
auto threadsResponse = session.send(threadsRequest).get();
ASSERT_TRUE(!threadsResponse.error);
// CMake only has one DAP thread. Once that thread exits, there should be
// no threads left.
ASSERT_TRUE(threadsResponse.response.threads.empty());
return true;
});
}
int testDebuggerAdapter(int, char*[])
{
return runTests(std::vector<std::function<bool()>>{
testBasicProtocol,
testThreadsRequestAfterThreadExitedEvent,
});
}