[Lldb-commits] [lldb] 0adf9b6 - [lldb-dap] Address a race condition in server mode. (#191062)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Apr 10 08:48:48 PDT 2026
Author: John Harrison
Date: 2026-04-10T08:48:42-07:00
New Revision: 0adf9b6f33d12e99284db70a1aef485fa6cabe3c
URL: https://github.com/llvm/llvm-project/commit/0adf9b6f33d12e99284db70a1aef485fa6cabe3c
DIFF: https://github.com/llvm/llvm-project/commit/0adf9b6f33d12e99284db70a1aef485fa6cabe3c.diff
LOG: [lldb-dap] Address a race condition in server mode. (#191062)
While running in server mode, multiple clients can be connected at the
same time. In LLDBUtils we had a static mutex that can cause other
clients to hang due to the single static lock.
Instead, I adjusted the logic to take the existing SBMutex as a paremter
and guard that mutex during command handling.
Added:
Modified:
lldb/tools/lldb-dap/DAP.cpp
lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
lldb/tools/lldb-dap/LLDBUtils.cpp
lldb/tools/lldb-dap/LLDBUtils.h
Removed:
################################################################################
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index f1ebe9b316496..7b58fca0f8163 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -704,7 +704,7 @@ bool DAP::RunLLDBCommands(llvm::StringRef prefix,
llvm::ArrayRef<String> commands) {
bool required_command_failed = false;
std::string output = ::RunLLDBCommands(
- debugger, prefix, commands, required_command_failed,
+ debugger, GetAPIMutex(), prefix, commands, required_command_failed,
/*parse_command_directives*/ true, /*echo_commands*/ true);
SendOutput(OutputType::Console, output);
return !required_command_failed;
diff --git a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
index 906f262779e1d..7537eca72ec25 100644
--- a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
@@ -93,7 +93,8 @@ EvaluateRequestHandler::Run(const EvaluateArguments &arguments) const {
bool required_command_failed = false;
body.result = RunLLDBCommands(
- dap.debugger, llvm::StringRef(), {expression}, required_command_failed,
+ dap.debugger, dap.GetAPIMutex(), llvm::StringRef(), {expression},
+ required_command_failed,
/*parse_command_directives=*/false, /*echo_commands=*/false);
return body;
}
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index 95eb85b7f2226..826598f260ef5 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -13,6 +13,7 @@
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBFrame.h"
+#include "lldb/API/SBMutex.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBThread.h"
@@ -31,10 +32,10 @@
namespace lldb_dap {
-bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
- const llvm::ArrayRef<protocol::String> &commands,
- llvm::raw_ostream &strm, bool parse_command_directives,
- bool echo_commands) {
+static bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
+ const llvm::ArrayRef<protocol::String> &commands,
+ llvm::raw_ostream &strm,
+ bool parse_command_directives, bool echo_commands) {
if (commands.empty())
return true;
@@ -74,15 +75,8 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
}
}
- {
- // Prevent simultaneous calls to HandleCommand, e.g. EventThreadFunction
- // may asynchronously call RunExitCommands when we are already calling
- // RunTerminateCommands.
- static std::mutex handle_command_mutex;
- std::lock_guard<std::mutex> locker(handle_command_mutex);
- interp.HandleCommand(command.str().c_str(), result,
- /*add_to_history=*/true);
- }
+ interp.HandleCommand(command.str().c_str(), result,
+ /*add_to_history=*/true);
const bool got_error = !result.Succeeded();
// The if statement below is assuming we always print out `!` prefixed
@@ -114,10 +108,13 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
return true;
}
-std::string RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
+std::string RunLLDBCommands(lldb::SBDebugger &debugger, lldb::SBMutex mutex,
+ llvm::StringRef prefix,
const llvm::ArrayRef<protocol::String> &commands,
bool &required_command_failed,
bool parse_command_directives, bool echo_commands) {
+ // Ensure a single command is evaluated at a time.
+ std::lock_guard<lldb::SBMutex> guard(mutex);
required_command_failed = false;
std::string s;
llvm::raw_string_ostream strm(s);
diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h
index 3565b398160e7..30882b75fa359 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.h
+++ b/lldb/tools/lldb-dap/LLDBUtils.h
@@ -28,46 +28,6 @@
namespace lldb_dap {
-/// Run a list of LLDB commands in the LLDB command interpreter.
-///
-/// All output from every command, including the prompt + the command
-/// is placed into the "strm" argument.
-///
-/// Each individual command can be prefixed with \b ! and/or \b ? in no
-/// particular order. If \b ? is provided, then the output of that command is
-/// only emitted if it fails, and if \b ! is provided, then the output is
-/// emitted regardless, and \b false is returned without executing the
-/// remaining commands.
-///
-/// \param[in] debugger
-/// The debugger that will execute the lldb commands.
-///
-/// \param[in] prefix
-/// A string that will be printed into \a strm prior to emitting
-/// the prompt + command and command output. Can be NULL.
-///
-/// \param[in] commands
-/// An array of LLDB commands to execute.
-///
-/// \param[in] strm
-/// The stream that will receive the prefix, prompt + command and
-/// all command output.
-///
-/// \param[in] parse_command_directives
-/// If \b false, then command prefixes like \b ! or \b ? are not parsed and
-/// each command is executed verbatim.
-///
-/// \param[in] echo_commands
-/// If \b true, the command are echoed to the stream.
-///
-/// \return
-/// \b true, unless a command prefixed with \b ! fails and parsing of
-/// command directives is enabled.
-bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
- const llvm::ArrayRef<protocol::String> &commands,
- llvm::raw_ostream &strm, bool parse_command_directives,
- bool echo_commands);
-
/// Run a list of LLDB commands in the LLDB command interpreter.
///
/// All output from every command, including the prompt + the command
@@ -76,6 +36,9 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
/// \param[in] debugger
/// The debugger that will execute the lldb commands.
///
+/// \param[in] mutex
+/// The mutex protecting this target.
+///
/// \param[in] prefix
/// A string that will be printed into \a strm prior to emitting
/// the prompt + command and command output. Can be NULL.
@@ -97,7 +60,8 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
/// \return
/// A std::string that contains the prefix and all commands and
/// command output.
-std::string RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
+std::string RunLLDBCommands(lldb::SBDebugger &debugger, lldb::SBMutex mutex,
+ llvm::StringRef prefix,
const llvm::ArrayRef<protocol::String> &commands,
bool &required_command_failed,
bool parse_command_directives = true,
More information about the lldb-commits
mailing list