aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Commands/CommandObjectCommands.cpp
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2025-02-19 20:32:00 -0800
committerGitHub <noreply@github.com>2025-02-19 20:32:00 -0800
commit58279d1ee1b567e8ca793d6d1eb6e0f1d5e7279e (patch)
tree4e1c25b423d78f003b9a781d7753600867465b9f /lldb/source/Commands/CommandObjectCommands.cpp
parent557628dbe6a935b1ad5e1bcfd51ac3a65e35d874 (diff)
downloadllvm-58279d1ee1b567e8ca793d6d1eb6e0f1d5e7279e.zip
llvm-58279d1ee1b567e8ca793d6d1eb6e0f1d5e7279e.tar.gz
llvm-58279d1ee1b567e8ca793d6d1eb6e0f1d5e7279e.tar.bz2
[lldb] Synchronize the debuggers output & error streams
This patch improves the synchronization of the debugger's output and error streams using two new abstractions: `LockableStreamFile` and `LockedStreamFile`. - `LockableStreamFile` is a wrapper around a `StreamFile` and a mutex. Client cannot use the `StreamFile` without calling `Lock`, which returns a `LockedStreamFile`. - `LockedStreamFile` is an RAII object that locks the stream for the duration of its existence. As long as you hold on to the returned object you are permitted to write to the stream. The destruction of the object automatically flush the output stream.
Diffstat (limited to 'lldb/source/Commands/CommandObjectCommands.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp62
1 files changed, 36 insertions, 26 deletions
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index f069b2f..dd841cb 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -11,6 +11,7 @@
#include "CommandObjectRegexCommand.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandHistory.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
@@ -792,12 +793,15 @@ a number follows 'f':"
protected:
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString("Enter one or more sed substitution commands in "
- "the form: 's/<regex>/<subst>/'.\nTerminate the "
- "substitution list with an empty line.\n");
- output_sp->Flush();
+ if (interactive) {
+ if (lldb::LockableStreamFileSP output_sp =
+ io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(
+ "Enter one or more sed substitution commands in "
+ "the form: 's/<regex>/<subst>/'.\nTerminate the "
+ "substitution list with an empty line.\n");
+ }
}
}
@@ -2377,16 +2381,18 @@ protected:
};
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString(g_python_command_instructions);
- output_sp->Flush();
+ if (interactive) {
+ if (lldb::LockableStreamFileSP output_sp =
+ io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(g_python_command_instructions);
+ }
}
}
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override {
- StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
+ LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
if (interpreter) {
@@ -2396,9 +2402,10 @@ protected:
std::string funct_name_str;
if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
if (funct_name_str.empty()) {
- error_sp->Printf("error: unable to obtain a function name, didn't "
- "add python command.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
+ "error: unable to obtain a function name, didn't "
+ "add python command.\n");
} else {
// everything should be fine now, let's add this alias
@@ -2409,33 +2416,36 @@ protected:
Status error = m_interpreter.AddUserCommand(
m_cmd_name, command_obj_sp, m_overwrite);
if (error.Fail()) {
- error_sp->Printf("error: unable to add selected command: '%s'",
- error.AsCString());
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
+ "error: unable to add selected command: '%s'",
+ error.AsCString());
}
} else {
llvm::Error llvm_error = m_container->LoadUserSubcommand(
m_cmd_name, command_obj_sp, m_overwrite);
if (llvm_error) {
- error_sp->Printf("error: unable to add selected command: '%s'",
- llvm::toString(std::move(llvm_error)).c_str());
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
+ "error: unable to add selected command: '%s'",
+ llvm::toString(std::move(llvm_error)).c_str());
}
}
}
} else {
- error_sp->Printf(
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
"error: unable to create function, didn't add python command\n");
- error_sp->Flush();
}
} else {
- error_sp->Printf("error: empty function, didn't add python command\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
+ "error: empty function, didn't add python command\n");
}
} else {
- error_sp->Printf(
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
"error: script interpreter missing, didn't add python command\n");
- error_sp->Flush();
}
io_handler.SetIsDone(true);