JDevlieghere updated this revision to Diff 272825.
JDevlieghere added a comment.
Consume the error when the result pointer is null.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D82396/new/
https://reviews.llvm.org/D82396
Files:
lldb/include/lldb/Interpreter/ScriptInterpreter.h
lldb/source/Interpreter/ScriptInterpreter.cpp
lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -42,6 +42,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
@@ -895,15 +896,6 @@
return m_run_one_line_function.IsValid();
}
-static void ReadThreadBytesReceived(void *baton, const void *src,
- size_t src_len) {
- if (src && src_len) {
- Stream *strm = (Stream *)baton;
- strm->Write(src, src_len);
- strm->Flush();
- }
-}
-
bool ScriptInterpreterPythonImpl::ExecuteOneLine(
llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options) {
@@ -919,75 +911,21 @@
// another string to pass to PyRun_SimpleString messes up the escaping. So
// we use the following more complicated method to pass the command string
// directly down to Python.
- Debugger &debugger = m_debugger;
-
- FileSP input_file_sp;
- StreamFileSP output_file_sp;
- StreamFileSP error_file_sp;
- Communication output_comm(
- "lldb.ScriptInterpreterPythonImpl.ExecuteOneLine.comm");
- bool join_read_thread = false;
+ std::unique_ptr<ScriptInterpreterIORedirect> io_redirect;
if (options.GetEnableIO()) {
- if (result) {
- input_file_sp = debugger.GetInputFileSP();
- // Set output to a temporary file so we can forward the results on to
- // the result object
-
- Pipe pipe;
- Status pipe_result = pipe.CreateNew(false);
- if (pipe_result.Success()) {
-#if defined(_WIN32)
- lldb::file_t read_file = pipe.GetReadNativeHandle();
- pipe.ReleaseReadFileDescriptor();
- std::unique_ptr<ConnectionGenericFile> conn_up(
- new ConnectionGenericFile(read_file, true));
-#else
- std::unique_ptr<ConnectionFileDescriptor> conn_up(
- new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(),
- true));
-#endif
- if (conn_up->IsConnected()) {
- output_comm.SetConnection(std::move(conn_up));
- output_comm.SetReadThreadBytesReceivedCallback(
- ReadThreadBytesReceived, &result->GetOutputStream());
- output_comm.StartReadThread();
- join_read_thread = true;
- FILE *outfile_handle =
- fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
- output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);
- error_file_sp = output_file_sp;
- if (outfile_handle)
- ::setbuf(outfile_handle, nullptr);
-
- result->SetImmediateOutputFile(
- debugger.GetOutputStream().GetFileSP());
- result->SetImmediateErrorFile(
- debugger.GetErrorStream().GetFileSP());
- }
- }
- }
- if (!input_file_sp || !output_file_sp || !error_file_sp)
- debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp,
- error_file_sp);
+ io_redirect =
+ std::make_unique<ScriptInterpreterIORedirect>(m_debugger, result);
} else {
- auto nullin = FileSystem::Instance().Open(
- FileSpec(FileSystem::DEV_NULL),
- File::eOpenOptionRead);
- auto nullout = FileSystem::Instance().Open(
- FileSpec(FileSystem::DEV_NULL),
- File::eOpenOptionWrite);
- if (!nullin) {
- result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n",
- llvm::fmt_consume(nullin.takeError()));
- return false;
- }
- if (!nullout) {
- result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n",
- llvm::fmt_consume(nullout.takeError()));
+ llvm::Error error = llvm::Error::success();
+ io_redirect = std::make_unique<ScriptInterpreterIORedirect>(error);
+ if (error) {
+ if (result)
+ result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n",
+ llvm::fmt_consume(std::move(error)));
+ else
+ llvm::consumeError(std::move(error));
return false;
}
- input_file_sp = std::move(nullin.get());
- error_file_sp = output_file_sp = std::make_shared<StreamFile>(std::move(nullout.get()));
}
bool success = false;
@@ -1005,8 +943,9 @@
Locker::AcquireLock | Locker::InitSession |
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
- Locker::FreeAcquiredLock | Locker::TearDownSession, input_file_sp,
- output_file_sp->GetFileSP(), error_file_sp->GetFileSP());
+ Locker::FreeAcquiredLock | Locker::TearDownSession,
+ io_redirect->GetInputFile(), io_redirect->GetOutputFile(),
+ io_redirect->GetErrorFile());
// Find the correct script interpreter dictionary in the main module.
PythonDictionary &session_dict = GetSessionDictionary();
@@ -1032,21 +971,7 @@
}
}
- // Flush our output and error file handles
- output_file_sp->Flush();
- error_file_sp->Flush();
- }
-
- if (join_read_thread) {
- // 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
- output_file_sp->GetFile().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
- output_comm.JoinReadThread();
- // Now we can close the read end of the pipe
- output_comm.Disconnect();
+ io_redirect->Flush();
}
if (success)
Index: lldb/source/Interpreter/ScriptInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/ScriptInterpreter.cpp
+++ lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -8,10 +8,14 @@
#include "lldb/Interpreter/ScriptInterpreter.h"
+#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <string>
+#include "lldb/Core/Debugger.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/Pipe.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Utility/Status.h"
@@ -105,3 +109,103 @@
return std::unique_ptr<ScriptInterpreterLocker>(
new ScriptInterpreterLocker());
}
+
+static void ReadThreadBytesReceived(void *baton, const void *src,
+ size_t src_len) {
+ if (src && src_len) {
+ Stream *strm = (Stream *)baton;
+ strm->Write(src, src_len);
+ strm->Flush();
+ }
+}
+
+ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(
+ Debugger &debugger, CommandReturnObject *result)
+ : m_communication("lldb.ScriptInterpreterIORedirect.comm"),
+ m_disconnect(false) {
+ if (result) {
+ m_input_file_sp = debugger.GetInputFileSP();
+
+ Pipe pipe;
+ Status pipe_result = pipe.CreateNew(false);
+#if defined(_WIN32)
+ lldb::file_t read_file = pipe.GetReadNativeHandle();
+ pipe.ReleaseReadFileDescriptor();
+ std::unique_ptr<ConnectionGenericFile> conn_up =
+ std::make_unique<ConnectionGenericFile>(read_file, true);
+#else
+ std::unique_ptr<ConnectionFileDescriptor> conn_up =
+ std::make_unique<ConnectionFileDescriptor>(
+ pipe.ReleaseReadFileDescriptor(), true);
+#endif
+
+ if (conn_up->IsConnected()) {
+ m_communication.SetConnection(std::move(conn_up));
+ m_communication.SetReadThreadBytesReceivedCallback(
+ ReadThreadBytesReceived, &result->GetOutputStream());
+ m_communication.StartReadThread();
+ m_disconnect = true;
+
+ FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
+ m_output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);
+ m_error_file_sp = m_output_file_sp;
+ if (outfile_handle)
+ ::setbuf(outfile_handle, nullptr);
+
+ result->SetImmediateOutputFile(debugger.GetOutputStream().GetFileSP());
+ result->SetImmediateErrorFile(debugger.GetErrorStream().GetFileSP());
+ }
+ }
+
+ if (!m_input_file_sp || !m_output_file_sp || !m_error_file_sp)
+ debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_file_sp, m_output_file_sp,
+ m_error_file_sp);
+}
+
+ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(llvm::Error &error)
+ : m_communication("lldb.ScriptInterpreterIORedirect.comm"),
+ m_disconnect(false) {
+ auto nullin = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),
+ File::eOpenOptionRead);
+ if (!nullin) {
+ error = nullin.takeError();
+ return;
+ }
+
+ auto nullout = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),
+ File::eOpenOptionWrite);
+ if (!nullout) {
+ error = nullout.takeError();
+ return;
+ }
+
+ m_input_file_sp = std::move(nullin.get());
+ m_error_file_sp = m_output_file_sp =
+ std::make_shared<StreamFile>(std::move(nullout.get()));
+}
+
+void ScriptInterpreterIORedirect::Flush() {
+ if (m_output_file_sp)
+ m_output_file_sp->Flush();
+ if (m_error_file_sp)
+ m_error_file_sp->Flush();
+}
+
+ScriptInterpreterIORedirect::~ScriptInterpreterIORedirect() {
+ if (!m_disconnect)
+ return;
+
+ assert(m_output_file_sp);
+ assert(m_error_file_sp);
+ assert(m_output_file_sp == m_error_file_sp);
+
+ // 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();
+ // 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();
+ // Now we can close the read end of the pipe.
+ m_communication.Disconnect();
+}
Index: lldb/include/lldb/Interpreter/ScriptInterpreter.h
===================================================================
--- lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -9,16 +9,16 @@
#ifndef LLDB_INTERPRETER_SCRIPTINTERPRETER_H
#define LLDB_INTERPRETER_SCRIPTINTERPRETER_H
-#include "lldb/lldb-private.h"
-
#include "lldb/Breakpoint/BreakpointOptions.h"
+#include "lldb/Core/Communication.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/SearchFilter.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
-
-#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -34,6 +34,32 @@
operator=(const ScriptInterpreterLocker &) = delete;
};
+class ScriptInterpreterIORedirect {
+public:
+ /// Create an IO redirect with /dev/null as input, output and error file.
+ ScriptInterpreterIORedirect(llvm::Error &error);
+
+ /// Create an IO redirect that redirects the output to the command return
+ /// object if set or to the debugger otherwise.
+ ScriptInterpreterIORedirect(Debugger &debugger, CommandReturnObject *result);
+
+ ~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(); }
+
+ /// Flush our output and error file handles.
+ void Flush();
+
+private:
+ lldb::FileSP m_input_file_sp;
+ lldb::StreamFileSP m_output_file_sp;
+ lldb::StreamFileSP m_error_file_sp;
+ Communication m_communication;
+ bool m_disconnect;
+};
+
class ScriptInterpreter : public PluginInterface {
public:
enum ScriptReturnType {
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits