aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/Debugger.h24
-rw-r--r--lldb/include/lldb/Core/IOHandler.h33
-rw-r--r--lldb/include/lldb/Host/Editline.h17
-rw-r--r--lldb/include/lldb/Host/File.h5
-rw-r--r--lldb/include/lldb/Host/StreamFile.h52
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreter.h19
-rw-r--r--lldb/include/lldb/lldb-forward.h2
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp10
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp62
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp9
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp35
-rw-r--r--lldb/source/Commands/CommandObjectType.cpp122
-rw-r--r--lldb/source/Commands/CommandObjectWatchpointCommand.cpp14
-rw-r--r--lldb/source/Core/Debugger.cpp36
-rw-r--r--lldb/source/Core/IOHandler.cpp91
-rw-r--r--lldb/source/Core/IOHandlerCursesGUI.cpp4
-rw-r--r--lldb/source/Expression/REPL.cpp10
-rw-r--r--lldb/source/Host/common/Editline.cpp130
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp26
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp13
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp24
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp35
-rw-r--r--lldb/unittests/Editline/EditlineTest.cpp13
23 files changed, 472 insertions, 314 deletions
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index 7f08f3d..9c8a962 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -131,13 +131,16 @@ public:
void SetAsyncExecution(bool async);
- File &GetInputFile() { return *m_input_file_sp; }
-
lldb::FileSP GetInputFileSP() { return m_input_file_sp; }
+ File &GetInputFile() { return *m_input_file_sp; }
- lldb::FileSP GetOutputFileSP() { return m_output_stream_sp->GetFileSP(); }
+ lldb::FileSP GetOutputFileSP() {
+ return m_output_stream_sp->GetUnlockedFileSP();
+ }
- lldb::FileSP GetErrorFileSP() { return m_error_stream_sp->GetFileSP(); }
+ lldb::FileSP GetErrorFileSP() {
+ return m_error_stream_sp->GetUnlockedFileSP();
+ }
repro::DataRecorder *GetInputRecorder();
@@ -198,8 +201,8 @@ public:
// If any of the streams are not set, set them to the in/out/err stream of
// the top most input reader to ensure they at least have something
void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in,
- lldb::StreamFileSP &out,
- lldb::StreamFileSP &err);
+ lldb::LockableStreamFileSP &out,
+ lldb::LockableStreamFileSP &err);
/// Run the given IO handler and return immediately.
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp,
@@ -649,8 +652,8 @@ protected:
/// should not be used directly. Use GetAsyncOutputStream and
/// GetAsyncErrorStream instead.
/// @{
- lldb::StreamFileSP GetOutputStreamSP() { return m_output_stream_sp; }
- lldb::StreamFileSP GetErrorStreamSP() { return m_error_stream_sp; }
+ lldb::LockableStreamFileSP GetOutputStreamSP() { return m_output_stream_sp; }
+ lldb::LockableStreamFileSP GetErrorStreamSP() { return m_error_stream_sp; }
/// @}
void PushIOHandler(const lldb::IOHandlerSP &reader_sp,
@@ -693,8 +696,9 @@ protected:
// these should never be NULL
lldb::FileSP m_input_file_sp;
- lldb::StreamFileSP m_output_stream_sp;
- lldb::StreamFileSP m_error_stream_sp;
+ lldb::LockableStreamFileSP m_output_stream_sp;
+ lldb::LockableStreamFileSP m_error_stream_sp;
+ LockableStreamFile::Mutex m_output_mutex;
/// Used for shadowing the input file when capturing a reproducer.
repro::DataRecorder *m_input_recorder;
diff --git a/lldb/include/lldb/Core/IOHandler.h b/lldb/include/lldb/Core/IOHandler.h
index d6ac1cc..fc0c676 100644
--- a/lldb/include/lldb/Core/IOHandler.h
+++ b/lldb/include/lldb/Core/IOHandler.h
@@ -53,8 +53,9 @@ public:
IOHandler(Debugger &debugger, IOHandler::Type type);
IOHandler(Debugger &debugger, IOHandler::Type type,
- const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp,
- const lldb::StreamFileSP &error_sp, uint32_t flags);
+ const lldb::FileSP &input_sp,
+ const lldb::LockableStreamFileSP &output_sp,
+ const lldb::LockableStreamFileSP &error_sp, uint32_t flags);
virtual ~IOHandler();
@@ -112,17 +113,11 @@ public:
int GetErrorFD();
- FILE *GetInputFILE();
-
- FILE *GetOutputFILE();
-
- FILE *GetErrorFILE();
-
lldb::FileSP GetInputFileSP();
- lldb::StreamFileSP GetOutputStreamFileSP();
+ lldb::LockableStreamFileSP GetOutputStreamFileSP();
- lldb::StreamFileSP GetErrorStreamFileSP();
+ lldb::LockableStreamFileSP GetErrorStreamFileSP();
Debugger &GetDebugger() { return m_debugger; }
@@ -155,14 +150,11 @@ public:
virtual void PrintAsync(const char *s, size_t len, bool is_stdout);
- std::recursive_mutex &GetOutputMutex() { return m_output_mutex; }
-
protected:
Debugger &m_debugger;
lldb::FileSP m_input_sp;
- lldb::StreamFileSP m_output_sp;
- lldb::StreamFileSP m_error_sp;
- std::recursive_mutex m_output_mutex;
+ lldb::LockableStreamFileSP m_output_sp;
+ lldb::LockableStreamFileSP m_error_sp;
Predicate<bool> m_popped;
Flags m_flags;
Type m_type;
@@ -330,8 +322,8 @@ public:
IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
const lldb::FileSP &input_sp,
- const lldb::StreamFileSP &output_sp,
- const lldb::StreamFileSP &error_sp, uint32_t flags,
+ const lldb::LockableStreamFileSP &output_sp,
+ const lldb::LockableStreamFileSP &error_sp, uint32_t flags,
const char *editline_name, // Used for saving history files
llvm::StringRef prompt, llvm::StringRef continuation_prompt,
bool multi_line, bool color,
@@ -345,9 +337,10 @@ public:
IOHandlerDelegate &) = delete;
IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::FileSP &,
- const lldb::StreamFileSP &, const lldb::StreamFileSP &,
- uint32_t, const char *, const char *, const char *, bool,
- bool, uint32_t, IOHandlerDelegate &) = delete;
+ const lldb::LockableStreamFileSP &,
+ const lldb::LockableStreamFileSP &, uint32_t, const char *,
+ const char *, const char *, bool, bool, uint32_t,
+ IOHandlerDelegate &) = delete;
~IOHandlerEditline() override;
diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h
index 27b8638..8964d37 100644
--- a/lldb/include/lldb/Host/Editline.h
+++ b/lldb/include/lldb/Host/Editline.h
@@ -34,6 +34,7 @@
#include <sstream>
#include <vector>
+#include "lldb/Host/StreamFile.h"
#include "lldb/lldb-private.h"
#if !defined(_WIN32) && !defined(__ANDROID__)
@@ -151,8 +152,9 @@ using namespace line_editor;
/// facility. Both single- and multi-line editing are supported.
class Editline {
public:
- Editline(const char *editor_name, FILE *input_file, FILE *output_file,
- FILE *error_file, bool color, std::recursive_mutex &output_mutex);
+ Editline(const char *editor_name, FILE *input_file,
+ lldb::LockableStreamFileSP output_stream_sp,
+ lldb::LockableStreamFileSP error_stream_sp, bool color);
~Editline();
@@ -237,7 +239,8 @@ public:
/// Prompts for and reads a multi-line batch of user input.
bool GetLines(int first_line_number, StringList &lines, bool &interrupted);
- void PrintAsync(Stream *stream, const char *s, size_t len);
+ void PrintAsync(lldb::LockableStreamFileSP stream_sp, const char *s,
+ size_t len);
/// Convert the current input lines into a UTF8 StringList
StringList GetInputAsStringList(int line_count = UINT32_MAX);
@@ -392,8 +395,11 @@ private:
volatile std::sig_atomic_t m_terminal_size_has_changed = 0;
std::string m_editor_name;
FILE *m_input_file;
- FILE *m_output_file;
- FILE *m_error_file;
+ lldb::LockableStreamFileSP m_output_stream_sp;
+ lldb::LockableStreamFileSP m_error_stream_sp;
+
+ std::optional<LockedStreamFile> m_locked_output;
+
ConnectionFileDescriptor m_input_connection;
IsInputCompleteCallbackType m_is_input_complete_callback;
@@ -411,7 +417,6 @@ private:
std::string m_suggestion_ansi_suffix;
std::size_t m_previous_autosuggestion_size = 0;
- std::recursive_mutex &m_output_mutex;
};
}
diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h
index 5ce53c9..9e2d0ab 100644
--- a/lldb/include/lldb/Host/File.h
+++ b/lldb/include/lldb/Host/File.h
@@ -377,6 +377,11 @@ private:
class NativeFile : public File {
public:
+ enum TransferOwnership : bool {
+ Owned = true,
+ Unowned = false,
+ };
+
NativeFile() : m_descriptor(kInvalidDescriptor), m_stream(kInvalidStream) {}
NativeFile(FILE *fh, bool transfer_ownership)
diff --git a/lldb/include/lldb/Host/StreamFile.h b/lldb/include/lldb/Host/StreamFile.h
index 2c96e13..e37661a 100644
--- a/lldb/include/lldb/Host/StreamFile.h
+++ b/lldb/include/lldb/Host/StreamFile.h
@@ -13,9 +13,12 @@
#include "lldb/Utility/Stream.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
#include <cstdint>
#include <cstdio>
+#include <memory>
+#include <mutex>
namespace lldb_private {
@@ -52,6 +55,55 @@ private:
const StreamFile &operator=(const StreamFile &) = delete;
};
+class LockableStreamFile;
+class LockedStreamFile : public StreamFile {
+public:
+ ~LockedStreamFile() { Flush(); }
+
+ LockedStreamFile(LockedStreamFile &&other)
+ : StreamFile(other.m_file_sp), m_lock(std::move(other.m_lock)) {}
+
+private:
+ LockedStreamFile(std::shared_ptr<File> file, std::recursive_mutex &mutex)
+ : StreamFile(file), m_lock(mutex) {}
+
+ friend class LockableStreamFile;
+
+ std::unique_lock<std::recursive_mutex> m_lock;
+};
+
+class LockableStreamFile {
+public:
+ using Mutex = std::recursive_mutex;
+
+ LockableStreamFile(std::shared_ptr<StreamFile> stream_file_sp, Mutex &mutex)
+ : m_file_sp(stream_file_sp->GetFileSP()), m_mutex(mutex) {}
+ LockableStreamFile(StreamFile &stream_file, Mutex &mutex)
+ : m_file_sp(stream_file.GetFileSP()), m_mutex(mutex) {}
+ LockableStreamFile(FILE *fh, bool transfer_ownership, Mutex &mutex)
+ : m_file_sp(std::make_shared<NativeFile>(fh, transfer_ownership)),
+ m_mutex(mutex) {}
+ LockableStreamFile(std::shared_ptr<File> file_sp, Mutex &mutex)
+ : m_file_sp(file_sp), m_mutex(mutex) {}
+
+ LockedStreamFile Lock() { return LockedStreamFile(m_file_sp, m_mutex); }
+
+ /// Unsafe accessors to get the underlying File without a lock. Exists for
+ /// legacy reasons.
+ /// @{
+ File &GetUnlockedFile() { return *m_file_sp; }
+ std::shared_ptr<File> GetUnlockedFileSP() { return m_file_sp; }
+ /// @}
+
+protected:
+ std::shared_ptr<File> m_file_sp;
+ Mutex &m_mutex;
+
+private:
+ LockableStreamFile(const LockableStreamFile &) = delete;
+ const LockableStreamFile &operator=(const LockableStreamFile &) = delete;
+};
+
} // namespace lldb_private
#endif // LLDB_HOST_STREAMFILE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 2c2bd6f..c5aa199 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -116,8 +116,12 @@ public:
~ScriptInterpreterIORedirect();
lldb::FileSP GetInputFile() const { return m_input_file_sp; }
- lldb::FileSP GetOutputFile() const { return m_output_file_sp->GetFileSP(); }
- lldb::FileSP GetErrorFile() const { return m_error_file_sp->GetFileSP(); }
+ lldb::FileSP GetOutputFile() const {
+ return m_output_file_sp->GetUnlockedFileSP();
+ }
+ lldb::FileSP GetErrorFile() const {
+ return m_error_file_sp->GetUnlockedFileSP();
+ }
/// Flush our output and error file handles.
void Flush();
@@ -128,8 +132,9 @@ private:
ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result);
lldb::FileSP m_input_file_sp;
- lldb::StreamFileSP m_output_file_sp;
- lldb::StreamFileSP m_error_file_sp;
+ lldb::LockableStreamFileSP m_output_file_sp;
+ lldb::LockableStreamFileSP m_error_file_sp;
+ LockableStreamFile::Mutex m_output_mutex;
ThreadedCommunication m_communication;
bool m_disconnect;
};
@@ -478,7 +483,7 @@ public:
dest.clear();
return false;
}
-
+
virtual StructuredData::ObjectSP
GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp) {
return {};
@@ -488,9 +493,9 @@ public:
GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp) {
return {};
}
-
+
virtual bool SetOptionValueForCommandObject(
- StructuredData::GenericSP cmd_obj_sp, ExecutionContext *exe_ctx,
+ StructuredData::GenericSP cmd_obj_sp, ExecutionContext *exe_ctx,
llvm::StringRef long_option, llvm::StringRef value) {
return false;
}
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index fc7456a..cda55ef 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -215,6 +215,7 @@ class StoppointCallbackContext;
class Stream;
class StreamFile;
class StreamString;
+class LockableStreamFile;
class StringList;
class StringTableReader;
class StructuredDataImpl;
@@ -432,6 +433,7 @@ typedef std::unique_ptr<lldb_private::StackFrameRecognizerManager>
typedef std::shared_ptr<lldb_private::StopInfo> StopInfoSP;
typedef std::shared_ptr<lldb_private::Stream> StreamSP;
typedef std::shared_ptr<lldb_private::StreamFile> StreamFileSP;
+typedef std::shared_ptr<lldb_private::LockableStreamFile> LockableStreamFileSP;
typedef std::shared_ptr<lldb_private::StringSummaryFormat>
StringTypeSummaryImplSP;
typedef std::unique_ptr<lldb_private::StructuredDataImpl> StructuredDataImplUP;
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index ac2db59..a913ed5 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -193,10 +193,12 @@ are no syntax errors may indicate that a function was declared but never called.
Options *GetOptions() override { return &m_all_options; }
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString(g_reader_instructions);
- output_sp->Flush();
+ if (interactive) {
+ if (lldb::LockableStreamFileSP output_sp =
+ io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(g_reader_instructions);
+ }
}
}
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);
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 18526c4..a95dea6 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -12,6 +12,7 @@
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -22,6 +23,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/DiagnosticsRendering.h"
#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
using namespace lldb;
@@ -544,11 +546,10 @@ void CommandObjectExpression::GetMultilineExpression() {
1, // Show line numbers starting at 1
*this));
- StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP();
- if (output_sp) {
- output_sp->PutCString(
+ if (LockableStreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(
"Enter expressions, then terminate with an empty line to evaluate:\n");
- output_sp->Flush();
}
debugger.RunIOHandlerAsync(io_handler_sp);
}
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 71ddc8d..bd9470b 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -57,6 +57,7 @@
#include "lldb/Utility/Timer.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -4923,11 +4924,13 @@ Filter Options:
protected:
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString(
- "Enter your stop hook command(s). Type 'DONE' to end.\n");
- output_sp->Flush();
+ if (interactive) {
+ if (lldb::LockableStreamFileSP output_sp =
+ io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(
+ "Enter your stop hook command(s). Type 'DONE' to end.\n");
+ }
}
}
@@ -4935,12 +4938,12 @@ protected:
std::string &line) override {
if (m_stop_hook_sp) {
if (line.empty()) {
- StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
- if (error_sp) {
- error_sp->Printf("error: stop hook #%" PRIu64
- " aborted, no commands.\n",
- m_stop_hook_sp->GetID());
- error_sp->Flush();
+ if (lldb::LockableStreamFileSP error_sp =
+ io_handler.GetErrorStreamFileSP()) {
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: stop hook #%" PRIu64
+ " aborted, no commands.\n",
+ m_stop_hook_sp->GetID());
}
GetTarget().UndoCreateStopHook(m_stop_hook_sp->GetID());
} else {
@@ -4949,11 +4952,11 @@ protected:
static_cast<Target::StopHookCommandLine *>(m_stop_hook_sp.get());
hook_ptr->SetActionFromString(line);
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp) {
- output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
- m_stop_hook_sp->GetID());
- output_sp->Flush();
+ if (lldb::LockableStreamFileSP output_sp =
+ io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.Printf("Stop hook #%" PRIu64 " added.\n",
+ m_stop_hook_sp->GetID());
}
}
m_stop_hook_sp.reset();
diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp
index e4c6e37..41630b6 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -14,6 +14,7 @@
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
@@ -32,6 +33,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StringList.h"
+#include "lldb/lldb-forward.h"
#include "llvm/ADT/STLExtras.h"
@@ -167,16 +169,17 @@ public:
"for\n"
" internal_dict: an LLDB support object not to be used\"\"\"\n";
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString(g_summary_addreader_instructions);
- output_sp->Flush();
+ if (interactive) {
+ if (LockableStreamFileSP output_sp = io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(g_summary_addreader_instructions);
+ }
}
}
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override {
- StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
+ LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
#if LLDB_ENABLE_PYTHON
ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
@@ -197,9 +200,10 @@ public:
if (interpreter->GenerateTypeScriptFunction(lines,
funct_name_str)) {
if (funct_name_str.empty()) {
- error_sp->Printf("unable to obtain a valid function name from "
- "the script interpreter.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
+ "unable to obtain a valid function name from "
+ "the script interpreter.\n");
} else {
// now I have a valid function name, let's add this as script
// for every type in the list
@@ -216,8 +220,8 @@ public:
options->m_match_type, options->m_category,
&error);
if (error.Fail()) {
- error_sp->Printf("error: %s", error.AsCString());
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: %s", error.AsCString());
}
}
@@ -228,41 +232,42 @@ public:
CommandObjectTypeSummaryAdd::AddNamedSummary(
options->m_name, script_format, &error);
if (error.Fail()) {
- error_sp->Printf("error: %s", error.AsCString());
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: %s", error.AsCString());
}
} else {
- error_sp->Printf("error: %s", error.AsCString());
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: %s", error.AsCString());
}
} else {
if (error.AsCString()) {
- error_sp->Printf("error: %s", error.AsCString());
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: %s", error.AsCString());
}
}
}
} else {
- error_sp->Printf("error: unable to generate a function.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: unable to generate a function.\n");
}
} else {
- error_sp->Printf("error: no script interpreter.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: no script interpreter.\n");
}
} else {
- error_sp->Printf("error: internal synchronization information "
- "missing or invalid.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: internal synchronization information "
+ "missing or invalid.\n");
}
} 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();
}
#endif
io_handler.SetIsDone(true);
@@ -404,16 +409,17 @@ protected:
}
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString(g_synth_addreader_instructions);
- output_sp->Flush();
+ if (interactive) {
+ if (LockableStreamFileSP output_sp = io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(g_synth_addreader_instructions);
+ }
}
}
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override {
- StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
+ LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
#if LLDB_ENABLE_PYTHON
ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
@@ -433,9 +439,10 @@ protected:
std::string class_name_str;
if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
if (class_name_str.empty()) {
- error_sp->Printf(
+
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
"error: unable to obtain a proper name for the class.\n");
- error_sp->Flush();
} else {
// everything should be fine now, let's add the synth provider
// class
@@ -459,37 +466,39 @@ protected:
if (AddSynth(ConstString(type_name), synth_provider,
options->m_match_type, options->m_category,
&error)) {
- error_sp->Printf("error: %s\n", error.AsCString());
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: %s\n", error.AsCString());
break;
}
} else {
- error_sp->Printf("error: invalid type name.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: invalid type name.\n");
break;
}
}
}
} else {
- error_sp->Printf("error: unable to generate a class.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: unable to generate a class.\n");
}
} else {
- error_sp->Printf("error: no script interpreter.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("error: no script interpreter.\n");
}
} else {
- error_sp->Printf("error: internal synchronization data missing.\n");
- error_sp->Flush();
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf(
+ "error: internal synchronization data missing.\n");
}
} 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();
}
#endif
@@ -952,8 +961,8 @@ protected:
class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete {
public:
CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
- : CommandObjectTypeFormatterDelete(
- interpreter, eFormatCategoryItemFormat) {}
+ : CommandObjectTypeFormatterDelete(interpreter,
+ eFormatCategoryItemFormat) {}
~CommandObjectTypeFormatDelete() override = default;
};
@@ -1603,8 +1612,8 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete {
public:
CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter)
- : CommandObjectTypeFormatterDelete(
- interpreter, eFormatCategoryItemSummary) {}
+ : CommandObjectTypeFormatterDelete(interpreter,
+ eFormatCategoryItemSummary) {}
~CommandObjectTypeSummaryDelete() override = default;
@@ -2070,8 +2079,8 @@ public:
class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete {
public:
CommandObjectTypeFilterDelete(CommandInterpreter &interpreter)
- : CommandObjectTypeFormatterDelete(
- interpreter, eFormatCategoryItemFilter) {}
+ : CommandObjectTypeFormatterDelete(interpreter,
+ eFormatCategoryItemFilter) {}
~CommandObjectTypeFilterDelete() override = default;
};
@@ -2081,13 +2090,12 @@ public:
class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete {
public:
CommandObjectTypeSynthDelete(CommandInterpreter &interpreter)
- : CommandObjectTypeFormatterDelete(
- interpreter, eFormatCategoryItemSynth) {}
+ : CommandObjectTypeFormatterDelete(interpreter,
+ eFormatCategoryItemSynth) {}
~CommandObjectTypeSynthDelete() override = default;
};
-
// CommandObjectTypeFilterClear
class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear {
diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
index ab1a2b3..507ef3f 100644
--- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -14,11 +14,13 @@
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"
+#include "lldb/lldb-forward.h"
using namespace lldb;
using namespace lldb_private;
@@ -170,11 +172,13 @@ are no syntax errors may indicate that a function was declared but never called.
Options *GetOptions() override { return &m_options; }
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString(
- "Enter your debugger command(s). Type 'DONE' to end.\n");
- output_sp->Flush();
+ if (interactive) {
+ if (lldb::LockableStreamFileSP output_sp =
+ io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream.PutCString(
+ "Enter your debugger command(s). Type 'DONE' to end.\n");
+ }
}
}
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 8b7814d..242ef1c 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -873,9 +873,11 @@ llvm::StringRef Debugger::GetStaticBroadcasterClass() {
Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
: UserID(g_unique_id++),
Properties(std::make_shared<OptionValueProperties>()),
- m_input_file_sp(std::make_shared<NativeFile>(stdin, false)),
- m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)),
- m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)),
+ m_input_file_sp(std::make_shared<NativeFile>(stdin, NativeFile::Unowned)),
+ m_output_stream_sp(std::make_shared<LockableStreamFile>(
+ stdout, NativeFile::Unowned, m_output_mutex)),
+ m_error_stream_sp(std::make_shared<LockableStreamFile>(
+ stderr, NativeFile::Unowned, m_output_mutex)),
m_input_recorder(nullptr),
m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
m_terminal_state(), m_target_list(*this), m_platform_list(),
@@ -1083,12 +1085,14 @@ void Debugger::SetInputFile(FileSP file_sp) {
void Debugger::SetOutputFile(FileSP file_sp) {
assert(file_sp && file_sp->IsValid());
- m_output_stream_sp = std::make_shared<StreamFile>(file_sp);
+ m_output_stream_sp =
+ std::make_shared<LockableStreamFile>(file_sp, m_output_mutex);
}
void Debugger::SetErrorFile(FileSP file_sp) {
assert(file_sp && file_sp->IsValid());
- m_error_stream_sp = std::make_shared<StreamFile>(file_sp);
+ m_error_stream_sp =
+ std::make_shared<LockableStreamFile>(file_sp, m_output_mutex);
}
void Debugger::SaveInputTerminalState() {
@@ -1198,9 +1202,10 @@ bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout);
if (!printed) {
- lldb::StreamFileSP stream =
+ LockableStreamFileSP stream_sp =
is_stdout ? m_output_stream_sp : m_error_stream_sp;
- stream->Write(s, len);
+ LockedStreamFile locked_stream = stream_sp->Lock();
+ locked_stream.Write(s, len);
}
}
@@ -1225,8 +1230,9 @@ void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp,
PushIOHandler(reader_sp, cancel_top_handler);
}
-void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
- StreamFileSP &err) {
+void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in,
+ LockableStreamFileSP &out,
+ LockableStreamFileSP &err) {
// Before an IOHandler runs, it must have in/out/err streams. This function
// is called when one ore more of the streams are nullptr. We use the top
// input reader's in/out/err streams, or fall back to the debugger file
@@ -1242,27 +1248,29 @@ void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
in = GetInputFileSP();
// If there is nothing, use stdin
if (!in)
- in = std::make_shared<NativeFile>(stdin, false);
+ in = std::make_shared<NativeFile>(stdin, NativeFile::Unowned);
}
// If no STDOUT has been set, then set it appropriately
- if (!out || !out->GetFile().IsValid()) {
+ if (!out || !out->GetUnlockedFile().IsValid()) {
if (top_reader_sp)
out = top_reader_sp->GetOutputStreamFileSP();
else
out = GetOutputStreamSP();
// If there is nothing, use stdout
if (!out)
- out = std::make_shared<StreamFile>(stdout, false);
+ out = std::make_shared<LockableStreamFile>(stdout, NativeFile::Unowned,
+ m_output_mutex);
}
// If no STDERR has been set, then set it appropriately
- if (!err || !err->GetFile().IsValid()) {
+ if (!err || !err->GetUnlockedFile().IsValid()) {
if (top_reader_sp)
err = top_reader_sp->GetErrorStreamFileSP();
else
err = GetErrorStreamSP();
// If there is nothing, use stderr
if (!err)
- err = std::make_shared<StreamFile>(stderr, false);
+ err = std::make_shared<LockableStreamFile>(stderr, NativeFile::Unowned,
+ m_output_mutex);
}
}
diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp
index ca06b52..98d1475 100644
--- a/lldb/source/Core/IOHandler.cpp
+++ b/lldb/source/Core/IOHandler.cpp
@@ -54,17 +54,17 @@ using llvm::StringRef;
IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type)
: IOHandler(debugger, type,
- FileSP(), // Adopt STDIN from top input reader
- StreamFileSP(), // Adopt STDOUT from top input reader
- StreamFileSP(), // Adopt STDERR from top input reader
- 0 // Flags
+ FileSP(), // Adopt STDIN from top input reader
+ LockableStreamFileSP(), // Adopt STDOUT from top input reader
+ LockableStreamFileSP(), // Adopt STDERR from top input reader
+ 0 // Flags
) {}
IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type,
const lldb::FileSP &input_sp,
- const lldb::StreamFileSP &output_sp,
- const lldb::StreamFileSP &error_sp, uint32_t flags)
+ const lldb::LockableStreamFileSP &output_sp,
+ const lldb::LockableStreamFileSP &error_sp, uint32_t flags)
: m_debugger(debugger), m_input_sp(input_sp), m_output_sp(output_sp),
m_error_sp(error_sp), m_popped(false), m_flags(flags), m_type(type),
m_user_data(nullptr), m_done(false), m_active(false) {
@@ -81,30 +81,18 @@ int IOHandler::GetInputFD() {
}
int IOHandler::GetOutputFD() {
- return (m_output_sp ? m_output_sp->GetFile().GetDescriptor() : -1);
+ return (m_output_sp ? m_output_sp->GetUnlockedFile().GetDescriptor() : -1);
}
int IOHandler::GetErrorFD() {
- return (m_error_sp ? m_error_sp->GetFile().GetDescriptor() : -1);
-}
-
-FILE *IOHandler::GetInputFILE() {
- return (m_input_sp ? m_input_sp->GetStream() : nullptr);
-}
-
-FILE *IOHandler::GetOutputFILE() {
- return (m_output_sp ? m_output_sp->GetFile().GetStream() : nullptr);
-}
-
-FILE *IOHandler::GetErrorFILE() {
- return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr);
+ return (m_error_sp ? m_error_sp->GetUnlockedFile().GetDescriptor() : -1);
}
FileSP IOHandler::GetInputFileSP() { return m_input_sp; }
-StreamFileSP IOHandler::GetOutputStreamFileSP() { return m_output_sp; }
+LockableStreamFileSP IOHandler::GetOutputStreamFileSP() { return m_output_sp; }
-StreamFileSP IOHandler::GetErrorStreamFileSP() { return m_error_sp; }
+LockableStreamFileSP IOHandler::GetErrorStreamFileSP() { return m_error_sp; }
bool IOHandler::GetIsInteractive() {
return GetInputFileSP() ? GetInputFileSP()->GetIsInteractive() : false;
@@ -119,10 +107,9 @@ void IOHandler::SetPopped(bool b) { m_popped.SetValue(b, eBroadcastOnChange); }
void IOHandler::WaitForPop() { m_popped.WaitForValueEqualTo(true); }
void IOHandler::PrintAsync(const char *s, size_t len, bool is_stdout) {
- std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
- lldb::StreamFileSP stream = is_stdout ? m_output_sp : m_error_sp;
- stream->Write(s, len);
- stream->Flush();
+ lldb::LockableStreamFileSP stream_sp = is_stdout ? m_output_sp : m_error_sp;
+ LockedStreamFile locked_Stream = stream_sp->Lock();
+ locked_Stream.Write(s, len);
}
bool IOHandlerStack::PrintAsync(const char *s, size_t len, bool is_stdout) {
@@ -228,19 +215,20 @@ IOHandlerEditline::IOHandlerEditline(
llvm::StringRef prompt, llvm::StringRef continuation_prompt,
bool multi_line, bool color, uint32_t line_number_start,
IOHandlerDelegate &delegate)
- : IOHandlerEditline(debugger, type,
- FileSP(), // Inherit input from top input reader
- StreamFileSP(), // Inherit output from top input reader
- StreamFileSP(), // Inherit error from top input reader
- 0, // Flags
- editline_name, // Used for saving history files
- prompt, continuation_prompt, multi_line, color,
- line_number_start, delegate) {}
+ : IOHandlerEditline(
+ debugger, type,
+ FileSP(), // Inherit input from top input reader
+ LockableStreamFileSP(), // Inherit output from top input reader
+ LockableStreamFileSP(), // Inherit error from top input reader
+ 0, // Flags
+ editline_name, // Used for saving history files
+ prompt, continuation_prompt, multi_line, color, line_number_start,
+ delegate) {}
IOHandlerEditline::IOHandlerEditline(
Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp,
- const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp,
- uint32_t flags,
+ const lldb::LockableStreamFileSP &output_sp,
+ const lldb::LockableStreamFileSP &error_sp, uint32_t flags,
const char *editline_name, // Used for saving history files
llvm::StringRef prompt, llvm::StringRef continuation_prompt,
bool multi_line, bool color, uint32_t line_number_start,
@@ -256,15 +244,12 @@ IOHandlerEditline::IOHandlerEditline(
SetPrompt(prompt);
#if LLDB_ENABLE_LIBEDIT
- bool use_editline = false;
-
- use_editline = GetInputFILE() && GetOutputFILE() && GetErrorFILE() &&
- m_input_sp && m_input_sp->GetIsRealTerminal();
-
+ const bool use_editline = m_input_sp && m_output_sp && m_error_sp &&
+ m_input_sp->GetIsRealTerminal();
if (use_editline) {
- m_editline_up = std::make_unique<Editline>(editline_name, GetInputFILE(),
- GetOutputFILE(), GetErrorFILE(),
- m_color, GetOutputMutex());
+ m_editline_up = std::make_unique<Editline>(
+ editline_name, m_input_sp ? m_input_sp->GetStream() : nullptr,
+ m_output_sp, m_error_sp, m_color);
m_editline_up->SetIsInputCompleteCallback(
[this](Editline *editline, StringList &lines) {
return this->IsInputCompleteCallback(editline, lines);
@@ -366,8 +351,8 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
if (prompt && prompt[0]) {
if (m_output_sp) {
- m_output_sp->Printf("%s", prompt);
- m_output_sp->Flush();
+ LockedStreamFile locked_stream = m_output_sp->Lock();
+ locked_stream.Printf("%s", prompt);
}
}
}
@@ -380,7 +365,7 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
return false;
}
- FILE *in = GetInputFILE();
+ FILE *in = m_input_sp ? m_input_sp->GetStream() : nullptr;
char buffer[256];
if (!got_line && !in && m_input_sp) {
@@ -545,9 +530,10 @@ bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) {
std::string line;
if (m_base_line_number > 0 && GetIsInteractive()) {
if (m_output_sp) {
- m_output_sp->Printf("%u%s",
- m_base_line_number + (uint32_t)lines.GetSize(),
- GetPrompt() == nullptr ? " " : "");
+ LockedStreamFile locked_stream = m_output_sp->Lock();
+ locked_stream.Printf("%u%s",
+ m_base_line_number + (uint32_t)lines.GetSize(),
+ GetPrompt() == nullptr ? " " : "");
}
}
@@ -630,9 +616,8 @@ void IOHandlerEditline::GotEOF() {
void IOHandlerEditline::PrintAsync(const char *s, size_t len, bool is_stdout) {
#if LLDB_ENABLE_LIBEDIT
if (m_editline_up) {
- std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
- lldb::StreamFileSP stream = is_stdout ? m_output_sp : m_error_sp;
- m_editline_up->PrintAsync(stream.get(), s, len);
+ lldb::LockableStreamFileSP stream_sp = is_stdout ? m_output_sp : m_error_sp;
+ m_editline_up->PrintAsync(stream_sp, s, len);
} else
#endif
{
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index c5eed0c..ee6e847 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -7576,7 +7576,9 @@ IOHandlerCursesGUI::IOHandlerCursesGUI(Debugger &debugger)
void IOHandlerCursesGUI::Activate() {
IOHandler::Activate();
if (!m_app_up) {
- m_app_up = std::make_unique<Application>(GetInputFILE(), GetOutputFILE());
+ m_app_up = std::make_unique<Application>(
+ m_input_sp ? m_input_sp->GetStream() : nullptr,
+ m_output_sp ? m_input_sp->GetStream() : nullptr);
// This is both a window and a menu delegate
std::shared_ptr<ApplicationDelegate> app_delegate_sp(
diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp
index 4b53537..e5377d3 100644
--- a/lldb/source/Expression/REPL.cpp
+++ b/lldb/source/Expression/REPL.cpp
@@ -103,8 +103,8 @@ void REPL::IOHandlerActivated(IOHandler &io_handler, bool interactive) {
lldb::ProcessSP process_sp = m_target.GetProcessSP();
if (process_sp && process_sp->IsAlive())
return;
- lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
- error_sp->Printf("REPL requires a running target process.\n");
+ LockedStreamFile locked_stream = io_handler.GetErrorStreamFileSP()->Lock();
+ locked_stream.Printf("REPL requires a running target process.\n");
io_handler.SetIsDone(true);
}
@@ -219,8 +219,10 @@ static bool ReadCode(const std::string &path, std::string &code,
}
void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
- lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
+ lldb::StreamFileSP output_sp = std::make_shared<StreamFile>(
+ io_handler.GetOutputStreamFileSP()->GetUnlockedFileSP());
+ lldb::StreamFileSP error_sp = std::make_shared<StreamFile>(
+ io_handler.GetErrorStreamFileSP()->GetUnlockedFileSP());
bool extra_line = false;
bool did_quit = false;
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index 73da1d84..5f7a8b0 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -14,6 +14,7 @@
#include "lldb/Host/Editline.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/FileSpec.h"
@@ -23,6 +24,7 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/Timeout.h"
+#include "lldb/lldb-forward.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
@@ -77,6 +79,19 @@ using namespace lldb_private::line_editor;
#endif // #if LLDB_EDITLINE_USE_WCHAR
+template <typename T> class ScopedOptional {
+public:
+ template <typename... Args>
+ ScopedOptional(std::optional<T> &optional, Args &&...args)
+ : m_optional(optional) {
+ m_optional.emplace(std::forward<Args>(args)...);
+ }
+ ~ScopedOptional() { m_optional.reset(); }
+
+private:
+ std::optional<T> &m_optional;
+};
+
bool IsOnlySpaces(const EditLineStringType &content) {
for (wchar_t ch : content) {
if (ch != EditLineCharType(' '))
@@ -389,11 +404,13 @@ void Editline::MoveCursor(CursorLocation from, CursorLocation to) {
(int)((info->cursor - info->buffer) + GetPromptWidth());
int editline_cursor_row = editline_cursor_position / m_terminal_width;
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
+
// Determine relative starting and ending lines
int fromLine = GetLineIndexForLocation(from, editline_cursor_row);
int toLine = GetLineIndexForLocation(to, editline_cursor_row);
if (toLine != fromLine) {
- fprintf(m_output_file,
+ fprintf(locked_stream.GetFile().GetStream(),
(toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS,
std::abs(toLine - fromLine));
}
@@ -409,21 +426,23 @@ void Editline::MoveCursor(CursorLocation from, CursorLocation to) {
80) +
1;
}
- fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn);
+ fprintf(locked_stream.GetFile().GetStream(), ANSI_SET_COLUMN_N, toColumn);
}
void Editline::DisplayInput(int firstIndex) {
- fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1);
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
+ fprintf(locked_stream.GetFile().GetStream(),
+ ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1);
int line_count = (int)m_input_lines.size();
for (int index = firstIndex; index < line_count; index++) {
- fprintf(m_output_file,
+ fprintf(locked_stream.GetFile().GetStream(),
"%s"
"%s"
"%s" EditLineStringFormatSpec " ",
m_prompt_ansi_prefix.c_str(), PromptForIndex(index).c_str(),
m_prompt_ansi_suffix.c_str(), m_input_lines[index].c_str());
if (index < line_count - 1)
- fprintf(m_output_file, "\n");
+ fprintf(locked_stream.GetFile().GetStream(), "\n");
}
}
@@ -535,8 +554,10 @@ int Editline::GetCharacter(EditLineGetCharType *c) {
// Paint a ANSI formatted version of the desired prompt over the version
// libedit draws. (will only be requested if colors are supported)
if (m_needs_prompt_repaint) {
+ ScopedOptional<LockedStreamFile> scope(m_locked_output,
+ m_output_stream_sp->Lock());
MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
- fprintf(m_output_file,
+ fprintf(m_locked_output->GetFile().GetStream(),
"%s"
"%s"
"%s",
@@ -574,10 +595,10 @@ int Editline::GetCharacter(EditLineGetCharType *c) {
// indefinitely. This gives a chance for someone to interrupt us. After
// Read returns, immediately lock the mutex again and check if we were
// interrupted.
- m_output_mutex.unlock();
+ m_locked_output.reset();
int read_count =
m_input_connection.Read(&ch, 1, std::nullopt, status, nullptr);
- m_output_mutex.lock();
+ m_locked_output.emplace(m_output_stream_sp->Lock());
if (m_editor_status == EditorStatus::Interrupted) {
while (read_count > 0 && status == lldb::eConnectionStatusSuccess)
read_count =
@@ -700,12 +721,14 @@ unsigned char Editline::EndOrAddLineCommand(int ch) {
}
}
MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd);
- fprintf(m_output_file, "\n");
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
+ fprintf(locked_stream.GetFile().GetStream(), "\n");
m_editor_status = EditorStatus::Complete;
return CC_NEWLINE;
}
unsigned char Editline::DeleteNextCharCommand(int ch) {
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
// Just delete the next character normally if possible
@@ -719,7 +742,7 @@ unsigned char Editline::DeleteNextCharCommand(int ch) {
// line is empty, in which case it is treated as EOF
if (m_current_line_index == m_input_lines.size() - 1) {
if (ch == 4 && info->buffer == info->lastchar) {
- fprintf(m_output_file, "^D\n");
+ fprintf(locked_stream.GetFile().GetStream(), "^D\n");
m_editor_status = EditorStatus::EndOfInput;
return CC_EOF;
}
@@ -767,7 +790,8 @@ unsigned char Editline::DeletePreviousCharCommand(int ch) {
priorLine + m_input_lines[m_current_line_index];
// Repaint from the new line down
- fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
+ fprintf(locked_stream.GetFile().GetStream(), ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
CountRowsForLine(priorLine), 1);
DisplayInput(m_current_line_index);
@@ -785,17 +809,19 @@ unsigned char Editline::PreviousLineCommand(int ch) {
return RecallHistory(HistoryOperation::Older);
}
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
+
// Start from a known location
MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
// Treat moving up from a blank last line as a deletion of that line
if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) {
m_input_lines.erase(m_input_lines.begin() + m_current_line_index);
- fprintf(m_output_file, ANSI_CLEAR_BELOW);
+ fprintf(locked_stream.GetFile().GetStream(), ANSI_CLEAR_BELOW);
}
SetCurrentLine(m_current_line_index - 1);
- fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
+ fprintf(locked_stream.GetFile().GetStream(), ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
CountRowsForLine(m_input_lines[m_current_line_index]), 1);
return CC_NEWLINE;
}
@@ -829,9 +855,11 @@ unsigned char Editline::NextLineCommand(int ch) {
const LineInfoW *info = el_wline(m_editline);
int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth());
int cursor_row = cursor_position / m_terminal_width;
+
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
for (int line_count = 0; line_count < m_current_line_rows - cursor_row;
line_count++) {
- fprintf(m_output_file, "\n");
+ fprintf(locked_stream.GetFile().GetStream(), "\n");
}
return CC_NEWLINE;
}
@@ -1031,7 +1059,9 @@ void Editline::DisplayCompletions(
Editline &editline, llvm::ArrayRef<CompletionResult::Completion> results) {
assert(!results.empty());
- fprintf(editline.m_output_file,
+ LockedStreamFile locked_stream = editline.m_output_stream_sp->Lock();
+
+ fprintf(locked_stream.GetFile().GetStream(),
"\n" ANSI_CLEAR_BELOW "Available completions:\n");
/// Account for the current line, the line showing "Available completions"
@@ -1049,15 +1079,15 @@ void Editline::DisplayCompletions(
size_t cur_pos = 0;
while (cur_pos < results.size()) {
- cur_pos +=
- PrintCompletion(editline.m_output_file, results.slice(cur_pos), max_len,
- editline.GetTerminalWidth(),
- all ? std::nullopt : std::optional<size_t>(page_size));
+ cur_pos += PrintCompletion(
+ locked_stream.GetFile().GetStream(), results.slice(cur_pos), max_len,
+ editline.GetTerminalWidth(),
+ all ? std::nullopt : std::optional<size_t>(page_size));
if (cur_pos >= results.size())
break;
- fprintf(editline.m_output_file, "More (Y/n/a): ");
+ fprintf(locked_stream.GetFile().GetStream(), "More (Y/n/a): ");
// The type for the output and the type for the parameter are different,
// to allow interoperability with older versions of libedit. The container
// for the reply must be as wide as what our implementation is using,
@@ -1069,11 +1099,11 @@ void Editline::DisplayCompletions(
// Check for a ^C or other interruption.
if (editline.m_editor_status == EditorStatus::Interrupted) {
editline.m_editor_status = EditorStatus::Editing;
- fprintf(editline.m_output_file, "^C\n");
+ fprintf(locked_stream.GetFile().GetStream(), "^C\n");
break;
}
- fprintf(editline.m_output_file, "\n");
+ fprintf(locked_stream.GetFile().GetStream(), "\n");
if (got_char == -1 || reply == 'n')
break;
if (reply == 'a')
@@ -1182,17 +1212,18 @@ unsigned char Editline::TypedCharacter(int ch) {
line_info->lastchar - line_info->buffer);
if (std::optional<std::string> to_add = m_suggestion_callback(line)) {
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
std::string to_add_color =
m_suggestion_ansi_prefix + to_add.value() + m_suggestion_ansi_suffix;
- fputs(typed.c_str(), m_output_file);
- fputs(to_add_color.c_str(), m_output_file);
+ fputs(typed.c_str(), locked_stream.GetFile().GetStream());
+ fputs(to_add_color.c_str(), locked_stream.GetFile().GetStream());
size_t new_autosuggestion_size = line.size() + to_add->length();
// Print spaces to hide any remains of a previous longer autosuggestion.
if (new_autosuggestion_size < m_previous_autosuggestion_size) {
size_t spaces_to_print =
m_previous_autosuggestion_size - new_autosuggestion_size;
std::string spaces = std::string(spaces_to_print, ' ');
- fputs(spaces.c_str(), m_output_file);
+ fputs(spaces.c_str(), locked_stream.GetFile().GetStream());
}
m_previous_autosuggestion_size = new_autosuggestion_size;
@@ -1201,7 +1232,7 @@ unsigned char Editline::TypedCharacter(int ch) {
int editline_cursor_row = editline_cursor_position / m_terminal_width;
int toColumn =
editline_cursor_position - (editline_cursor_row * m_terminal_width);
- fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn);
+ fprintf(locked_stream.GetFile().GetStream(), ANSI_SET_COLUMN_N, toColumn);
return CC_REFRESH;
}
@@ -1236,13 +1267,17 @@ void Editline::ConfigureEditor(bool multiline) {
el_end(m_editline);
}
- m_editline =
- el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file);
+ LockedStreamFile locked_output_stream = m_output_stream_sp->Lock();
+ LockedStreamFile locked_error_stream = m_output_stream_sp->Lock();
+ m_editline = el_init(m_editor_name.c_str(), m_input_file,
+ locked_output_stream.GetFile().GetStream(),
+ locked_error_stream.GetFile().GetStream());
ApplyTerminalSizeChange();
if (m_history_sp && m_history_sp->IsValid()) {
if (!m_history_sp->Load()) {
- fputs("Could not load history file\n.", m_output_file);
+ fputs("Could not load history file\n.",
+ locked_output_stream.GetFile().GetStream());
}
el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr());
}
@@ -1473,12 +1508,12 @@ Editline *Editline::InstanceFor(EditLine *editline) {
}
Editline::Editline(const char *editline_name, FILE *input_file,
- FILE *output_file, FILE *error_file, bool color,
- std::recursive_mutex &output_mutex)
+ lldb::LockableStreamFileSP output_stream_sp,
+ lldb::LockableStreamFileSP error_stream_sp, bool color)
: m_editor_status(EditorStatus::Complete), m_input_file(input_file),
- m_output_file(output_file), m_error_file(error_file),
- m_input_connection(fileno(input_file), false), m_color(color),
- m_output_mutex(output_mutex) {
+ m_output_stream_sp(output_stream_sp), m_error_stream_sp(error_stream_sp),
+ m_input_connection(fileno(input_file), false), m_color(color) {
+ assert(output_stream_sp && error_stream_sp);
// Get a shared history instance
m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name;
m_history_sp = EditlineHistory::GetHistory(m_editor_name);
@@ -1552,9 +1587,9 @@ uint32_t Editline::GetCurrentLine() { return m_current_line_index; }
bool Editline::Interrupt() {
bool result = true;
- std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
if (m_editor_status == EditorStatus::Editing) {
- fprintf(m_output_file, "^C\n");
+ fprintf(locked_stream.GetFile().GetStream(), "^C\n");
result = m_input_connection.InterruptRead();
}
m_editor_status = EditorStatus::Interrupted;
@@ -1563,10 +1598,10 @@ bool Editline::Interrupt() {
bool Editline::Cancel() {
bool result = true;
- std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
if (m_editor_status == EditorStatus::Editing) {
MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
- fprintf(m_output_file, ANSI_CLEAR_BELOW);
+ fprintf(locked_stream.GetFile().GetStream(), ANSI_CLEAR_BELOW);
result = m_input_connection.InterruptRead();
}
m_editor_status = EditorStatus::Interrupted;
@@ -1578,7 +1613,8 @@ bool Editline::GetLine(std::string &line, bool &interrupted) {
m_input_lines = std::vector<EditLineStringType>();
m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
- std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
+ ScopedOptional<LockedStreamFile> scope(m_locked_output,
+ m_output_stream_sp->Lock());
lldbassert(m_editor_status != EditorStatus::Editing);
if (m_editor_status == EditorStatus::Interrupted) {
@@ -1598,7 +1634,7 @@ bool Editline::GetLine(std::string &line, bool &interrupted) {
interrupted = m_editor_status == EditorStatus::Interrupted;
if (!interrupted) {
if (input == nullptr) {
- fprintf(m_output_file, "\n");
+ fprintf(m_locked_output->GetFile().GetStream(), "\n");
m_editor_status = EditorStatus::EndOfInput;
} else {
m_history_sp->Enter(input);
@@ -1623,7 +1659,9 @@ bool Editline::GetLines(int first_line_number, StringList &lines,
m_input_lines = std::vector<EditLineStringType>();
m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
- std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
+ ScopedOptional<LockedStreamFile> scope(m_locked_output,
+ m_output_stream_sp->Lock());
+
// Begin the line editing loop
DisplayInput();
SetCurrentLine(0);
@@ -1652,15 +1690,15 @@ bool Editline::GetLines(int first_line_number, StringList &lines,
return m_editor_status != EditorStatus::EndOfInput;
}
-void Editline::PrintAsync(Stream *stream, const char *s, size_t len) {
- std::lock_guard<std::recursive_mutex> guard(m_output_mutex);
+void Editline::PrintAsync(lldb::LockableStreamFileSP stream_sp, const char *s,
+ size_t len) {
+ LockedStreamFile locked_stream = m_output_stream_sp->Lock();
if (m_editor_status == EditorStatus::Editing) {
SaveEditedLine();
MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
- fprintf(m_output_file, ANSI_CLEAR_BELOW);
+ fprintf(locked_stream.GetFile().GetStream(), ANSI_CLEAR_BELOW);
}
- stream->Write(s, len);
- stream->Flush();
+ locked_stream.Write(s, len);
if (m_editor_status == EditorStatus::Editing) {
DisplayInput();
MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 5346d5a..c363f200 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -57,6 +57,7 @@
#include "lldb/Utility/Timer.h"
#include "lldb/Host/Config.h"
+#include "lldb/lldb-forward.h"
#if LLDB_ENABLE_LIBEDIT
#include "lldb/Host/Editline.h"
#endif
@@ -2843,7 +2844,7 @@ void CommandInterpreter::HandleCommandsFromFile(
// Used for inheriting the right settings when "command source" might
// have nested "command source" commands
- lldb::StreamFileSP empty_stream_sp;
+ lldb::LockableStreamFileSP empty_stream_sp;
m_command_source_flags.push_back(flags);
IOHandlerSP io_handler_sp(new IOHandlerEditline(
debugger, IOHandler::Type::CommandInterpreter, input_file_sp,
@@ -3100,25 +3101,26 @@ void CommandInterpreter::PrintCommandOutput(IOHandler &io_handler,
llvm::StringRef str,
bool is_stdout) {
- lldb::StreamFileSP stream = is_stdout ? io_handler.GetOutputStreamFileSP()
- : io_handler.GetErrorStreamFileSP();
+ lldb::LockableStreamFileSP stream = is_stdout
+ ? io_handler.GetOutputStreamFileSP()
+ : io_handler.GetErrorStreamFileSP();
// Split the output into lines and poll for interrupt requests
bool had_output = !str.empty();
while (!str.empty()) {
llvm::StringRef line;
std::tie(line, str) = str.split('\n');
{
- std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
- stream->Write(line.data(), line.size());
- stream->Write("\n", 1);
+ LockedStreamFile stream_file = stream->Lock();
+ stream_file.Write(line.data(), line.size());
+ stream_file.Write("\n", 1);
}
}
- std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
+ LockedStreamFile stream_file = stream->Lock();
if (had_output &&
INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping command output"))
- stream->Printf("\n... Interrupted.\n");
- stream->Flush();
+ stream_file.Printf("\n... Interrupted.\n");
+ stream_file.Flush();
}
bool CommandInterpreter::EchoCommandNonInteractive(
@@ -3160,9 +3162,9 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
// from a file) we need to echo the command out so we don't just see the
// command output and no command...
if (EchoCommandNonInteractive(line, io_handler.GetFlags())) {
- std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
- io_handler.GetOutputStreamFileSP()->Printf(
- "%s%s\n", io_handler.GetPrompt(), line.c_str());
+ LockedStreamFile locked_stream =
+ io_handler.GetOutputStreamFileSP()->Lock();
+ locked_stream.Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
}
}
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index a392d57..4424b6c 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -206,7 +206,8 @@ ScriptInterpreterIORedirect::Create(bool enable_io, Debugger &debugger,
ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(
std::unique_ptr<File> input, std::unique_ptr<File> output)
: m_input_file_sp(std::move(input)),
- m_output_file_sp(std::make_shared<StreamFile>(std::move(output))),
+ m_output_file_sp(std::make_shared<LockableStreamFile>(std::move(output),
+ m_output_mutex)),
m_error_file_sp(m_output_file_sp),
m_communication("lldb.ScriptInterpreterIORedirect.comm"),
m_disconnect(false) {}
@@ -240,7 +241,9 @@ ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(
m_disconnect = true;
FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
- m_output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);
+ m_output_file_sp = std::make_shared<LockableStreamFile>(
+ std::make_shared<StreamFile>(outfile_handle, NativeFile::Owned),
+ m_output_mutex);
m_error_file_sp = m_output_file_sp;
if (outfile_handle)
::setbuf(outfile_handle, nullptr);
@@ -257,9 +260,9 @@ ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(
void ScriptInterpreterIORedirect::Flush() {
if (m_output_file_sp)
- m_output_file_sp->Flush();
+ m_output_file_sp->Lock().Flush();
if (m_error_file_sp)
- m_error_file_sp->Flush();
+ m_error_file_sp->Lock().Flush();
}
ScriptInterpreterIORedirect::~ScriptInterpreterIORedirect() {
@@ -273,7 +276,7 @@ ScriptInterpreterIORedirect::~ScriptInterpreterIORedirect() {
// Close the write end of the pipe since we are done with our one line
// script. This should cause the read thread that output_comm is using to
// exit.
- m_output_file_sp->GetFile().Close();
+ m_output_file_sp->GetUnlockedFile().Close();
// The close above should cause this thread to exit when it gets to the end
// of file, so let it get all its data.
m_communication.JoinReadThread();
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
index 6d028e3..191863a 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -17,6 +17,7 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/Timer.h"
+#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FormatAdapters.h"
#include <memory>
@@ -76,8 +77,13 @@ public:
}
if (instructions == nullptr)
return;
- if (interactive)
- *io_handler.GetOutputStreamFileSP() << instructions;
+ if (interactive) {
+ if (lldb::LockableStreamFileSP output_sp =
+ io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = output_sp->Lock();
+ locked_stream << instructions;
+ }
+ }
}
bool IOHandlerIsInputComplete(IOHandler &io_handler,
@@ -112,8 +118,11 @@ public:
for (BreakpointOptions &bp_options : *bp_options_vec) {
Status error = m_script_interpreter.SetBreakpointCommandCallback(
bp_options, data.c_str(), /*is_callback=*/false);
- if (error.Fail())
- *io_handler.GetErrorStreamFileSP() << error.AsCString() << '\n';
+ if (error.Fail()) {
+ LockedStreamFile locked_stream =
+ io_handler.GetErrorStreamFileSP()->Lock();
+ locked_stream << error.AsCString() << '\n';
+ }
}
io_handler.SetIsDone(true);
} break;
@@ -130,8 +139,11 @@ public:
io_handler.SetIsDone(true);
return;
}
- if (llvm::Error error = m_script_interpreter.GetLua().Run(data))
- *io_handler.GetErrorStreamFileSP() << toString(std::move(error));
+ if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) {
+ LockedStreamFile locked_stream =
+ io_handler.GetErrorStreamFileSP()->Lock();
+ locked_stream << toString(std::move(error));
+ }
break;
}
}
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 9ea5b95..2b92bea 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -7,7 +7,10 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Config.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include <locale>
#if LLDB_ENABLE_PYTHON
@@ -489,11 +492,11 @@ def function (frame, bp_loc, internal_dict):
break;
}
- if (instructions) {
- StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
- if (output_sp && interactive) {
- output_sp->PutCString(instructions);
- output_sp->Flush();
+ if (instructions && interactive) {
+ if (LockableStreamFileSP stream_sp = io_handler.GetOutputStreamFileSP()) {
+ LockedStreamFile locked_stream = stream_sp->Lock();
+ locked_stream.PutCString(instructions);
+ locked_stream.Flush();
}
}
}
@@ -527,10 +530,9 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
bp_options.SetCallback(
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
} else if (!batch_mode) {
- StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
- if (error_sp) {
- error_sp->Printf("Warning: No command attached to breakpoint.\n");
- error_sp->Flush();
+ if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("Warning: No command attached to breakpoint.\n");
}
}
}
@@ -550,10 +552,9 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
wp_options->SetCallback(
ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
} else if (!batch_mode) {
- StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
- if (error_sp) {
- error_sp->Printf("Warning: No command attached to breakpoint.\n");
- error_sp->Flush();
+ if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) {
+ LockedStreamFile locked_stream = error_sp->Lock();
+ locked_stream.Printf("Warning: No command attached to breakpoint.\n");
}
}
m_active_io_handler = eIOHandlerNone;
@@ -680,7 +681,7 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
PythonDictionary &sys_module_dict = GetSysModuleDictionary();
if (sys_module_dict.IsValid()) {
lldb::FileSP top_in_sp;
- lldb::StreamFileSP top_out_sp, top_err_sp;
+ lldb::LockableStreamFileSP top_out_sp, top_err_sp;
if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp)
m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp,
top_err_sp);
@@ -696,12 +697,14 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) {
if (top_out_sp)
- SetStdHandle(top_out_sp->GetFileSP(), "stdout", m_saved_stdout, "w");
+ SetStdHandle(top_out_sp->GetUnlockedFileSP(), "stdout", m_saved_stdout,
+ "w");
}
if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) {
if (top_err_sp)
- SetStdHandle(top_err_sp->GetFileSP(), "stderr", m_saved_stderr, "w");
+ SetStdHandle(top_err_sp->GetUnlockedFileSP(), "stderr", m_saved_stderr,
+ "w");
}
}
diff --git a/lldb/unittests/Editline/EditlineTest.cpp b/lldb/unittests/Editline/EditlineTest.cpp
index 1327b58..6c5a0c9 100644
--- a/lldb/unittests/Editline/EditlineTest.cpp
+++ b/lldb/unittests/Editline/EditlineTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Config.h"
+#include "lldb/Host/File.h"
#if LLDB_ENABLE_LIBEDIT
@@ -25,6 +26,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/Host/StreamFile.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringList.h"
@@ -115,10 +117,17 @@ EditlineAdapter::EditlineAdapter()
if (*_el_secondary_file == nullptr)
return;
+ lldb::LockableStreamFileSP output_stream_sp =
+ std::make_shared<LockableStreamFile>(*_el_secondary_file,
+ NativeFile::Unowned, output_mutex);
+ lldb::LockableStreamFileSP error_stream_sp =
+ std::make_shared<LockableStreamFile>(*_el_secondary_file,
+ NativeFile::Unowned, output_mutex);
+
// Create an Editline instance.
_editline_sp.reset(new lldb_private::Editline(
- "gtest editor", *_el_secondary_file, *_el_secondary_file,
- *_el_secondary_file, /*color=*/false, output_mutex));
+ "gtest editor", *_el_secondary_file, output_stream_sp, error_stream_sp,
+ /*color=*/false));
_editline_sp->SetPrompt("> ");
// Hookup our input complete callback.