[Lldb-commits] [lldb] [lldb] Make SBProcess thread related actions listen to StopLocker (PR #134339)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Apr 10 20:06:15 PDT 2025
https://github.com/kusmour updated https://github.com/llvm/llvm-project/pull/134339
>From 0c4f6ca21ba6ae37e3a884f4bcc356b6f741ede7 Mon Sep 17 00:00:00 2001
From: Wanyi Ye <wanyi at meta.com>
Date: Thu, 3 Apr 2025 22:29:13 -0700
Subject: [PATCH 1/2] [lldb] Make SBProcess thread related actions listen to
StopLocker
---
lldb/source/API/SBProcess.cpp | 20 ++++++++++---------
.../tools/lldb-dap/attach/TestDAP_attach.py | 2 +-
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 23ea449b30cca..ba77b2beed5ea 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -193,10 +193,11 @@ uint32_t SBProcess::GetNumThreads() {
if (process_sp) {
Process::StopLocker stop_locker;
- const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
- std::lock_guard<std::recursive_mutex> guard(
- process_sp->GetTarget().GetAPIMutex());
- num_threads = process_sp->GetThreadList().GetSize(can_update);
+ if (stop_locker.TryLock(&process_sp->GetRunLock())) {
+ std::lock_guard<std::recursive_mutex> guard(
+ process_sp->GetTarget().GetAPIMutex());
+ num_threads = process_sp->GetThreadList().GetSize();
+ }
}
return num_threads;
@@ -393,11 +394,12 @@ SBThread SBProcess::GetThreadAtIndex(size_t index) {
ProcessSP process_sp(GetSP());
if (process_sp) {
Process::StopLocker stop_locker;
- const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
- std::lock_guard<std::recursive_mutex> guard(
- process_sp->GetTarget().GetAPIMutex());
- thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, can_update);
- sb_thread.SetThread(thread_sp);
+ if (stop_locker.TryLock(&process_sp->GetRunLock())) {
+ std::lock_guard<std::recursive_mutex> guard(
+ process_sp->GetTarget().GetAPIMutex());
+ thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, false);
+ sb_thread.SetThread(thread_sp);
+ }
}
return sb_thread;
diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
index 9df44cc454d5d..b9fbf2c8d14f9 100644
--- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
+++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py
@@ -1,5 +1,5 @@
"""
-Test lldb-dap setBreakpoints request
+Test lldb-dap attach request
"""
>From 931b3fbf9c31e4ea4e2c3bfe822ce0784c714c5a Mon Sep 17 00:00:00 2001
From: Wanyi Ye <wanyi at meta.com>
Date: Tue, 8 Apr 2025 22:52:19 -0700
Subject: [PATCH 2/2] [lldb-dap] Client expects initial threads request not
empty
---
.../test/tools/lldb-dap/dap_server.py | 4 ++++
lldb/tools/lldb-dap/DAP.h | 3 +++
.../ConfigurationDoneRequestHandler.cpp | 10 +++++++++-
.../lldb-dap/Handler/ThreadsRequestHandler.cpp | 18 ++++++++++++------
lldb/tools/lldb-dap/JSONUtils.cpp | 10 ++++++++++
lldb/tools/lldb-dap/JSONUtils.h | 2 ++
6 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 45403e9df8525..61d7fa94479b8 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -649,6 +649,10 @@ def request_configurationDone(self):
response = self.send_recv(command_dict)
if response:
self.configuration_done_sent = True
+ # Client requests the baseline of currently existing threads after
+ # a successful launch or attach.
+ # Kick off the threads request that follows
+ self.request_threads()
return response
def _process_stopped(self):
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index fc43d988f3a09..feeb040546c76 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -207,6 +207,9 @@ struct DAP {
/// The set of features supported by the connected client.
llvm::DenseSet<ClientFeature> clientFeatures;
+ /// The initial thread list upon attaching
+ std::optional<llvm::json::Array> initial_thread_list;
+
/// Creates a new DAP sessions.
///
/// \param[in] log
diff --git a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
index cd120e1fdfaba..f39bbdefdbb95 100644
--- a/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ConfigurationDoneRequestHandler.cpp
@@ -44,6 +44,7 @@ namespace lldb_dap {
// just an acknowledgement, so no body field is required."
// }]
// },
+
void ConfigurationDoneRequestHandler::operator()(
const llvm::json::Object &request) const {
llvm::json::Object response;
@@ -52,8 +53,15 @@ void ConfigurationDoneRequestHandler::operator()(
dap.configuration_done_sent = true;
if (dap.stop_at_entry)
SendThreadStoppedEvent(dap);
- else
+ else {
+ // Client requests the baseline of currently existing threads after
+ // a successful launch or attach by sending a 'threads' request
+ // right after receiving the configurationDone response.
+ // Obtain the list of threads before we resume the process
+ dap.initial_thread_list =
+ GetThreads(dap.target.GetProcess(), dap.thread_format);
dap.target.GetProcess().Continue();
+ }
}
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/ThreadsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ThreadsRequestHandler.cpp
index 2b857f7f6a02b..f4ddf8b90685c 100644
--- a/lldb/tools/lldb-dap/Handler/ThreadsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ThreadsRequestHandler.cpp
@@ -50,16 +50,22 @@ namespace lldb_dap {
// }
void ThreadsRequestHandler::operator()(
const llvm::json::Object &request) const {
- lldb::SBProcess process = dap.target.GetProcess();
llvm::json::Object response;
FillResponse(request, response);
- const uint32_t num_threads = process.GetNumThreads();
llvm::json::Array threads;
- for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
- lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
- threads.emplace_back(CreateThread(thread, dap.thread_format));
- }
+ // Client requests the baseline of currently existing threads after
+ // a successful launch or attach by sending a 'threads' request
+ // right after receiving the configurationDone response.
+ // If no thread has reported to the client, it prevents something
+ // like the pause request from working in the running state.
+ // Return the cache of initial threads as the process might have resumed
+ if (dap.initial_thread_list) {
+ threads = dap.initial_thread_list.value();
+ dap.initial_thread_list.reset();
+ } else
+ threads = GetThreads(dap.target.GetProcess(), dap.thread_format);
+
if (threads.size() == 0) {
response["success"] = llvm::json::Value(false);
}
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 7660403666150..4d317974cf2b2 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -870,6 +870,16 @@ llvm::json::Value CreateThread(lldb::SBThread &thread, lldb::SBFormat &format) {
return llvm::json::Value(std::move(object));
}
+llvm::json::Array GetThreads(lldb::SBProcess process, lldb::SBFormat &format) {
+ llvm::json::Array threads;
+ const uint32_t num_threads = process.GetNumThreads();
+ for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
+ lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
+ threads.emplace_back(CreateThread(thread, format));
+ }
+ return threads;
+}
+
// "StoppedEvent": {
// "allOf": [ { "$ref": "#/definitions/Event" }, {
// "type": "object",
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index da91797290ff0..b8c53353bf42d 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -414,6 +414,8 @@ llvm::json::Value CreateExtendedStackFrameLabel(lldb::SBThread &thread,
/// definition outlined by Microsoft.
llvm::json::Value CreateThread(lldb::SBThread &thread, lldb::SBFormat &format);
+llvm::json::Array GetThreads(lldb::SBProcess process, lldb::SBFormat &format);
+
/// Create a "StoppedEvent" object for a LLDB thread object.
///
/// This function will fill in the following keys in the returned
More information about the lldb-commits
mailing list