[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
labath added inline comments. Comment at: lldb/include/lldb/Interpreter/ScriptInterpreter.h:57-58 private: + friend std::unique_ptr + std::make_unique(); + labath wrote: > If that works, I suppose it's fine. But I wouldn't be surprised if this trick > backfires on some STL implementations. > > I think that making an exception for make_unique on classes with private > constructors is fine (we already have a bunch of classes like that)... BTW, i've just thought of another reason to not do the friend thingy -- making std::make_unique allows _anyone_ to construct this class via std::make_unique, which defeats the purpose of making the constructor private. OTOH, if we can successfully separate the fallible and infallible parts of the construction, then making the infallible part (constructor) public may not be that dangerous. For example, in this case, making the `(FileUP, FileUP)` constructor public might be ok. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82396/new/ https://reviews.llvm.org/D82396 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
This revision was automatically updated to reflect the committed changes. Closed by commit rGd79273c941d5: [lldb/ScriptInterpreter] Extract IO redirection logic (authored by JDevlieghere). Herald added a project: LLDB. Changed prior to commit: https://reviews.llvm.org/D82396?vs=273068=273429#toc Repository: rG LLVM Github Monorepo 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 ) { @@ -919,77 +911,23 @@ // 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 = 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; -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 conn_up( - new ConnectionGenericFile(read_file, true)); -#else - std::unique_ptr conn_up( - new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), - true)); -#endif - if (conn_up->IsConnected()) { -output_comm.SetConnection(std::move(conn_up)); -output_comm.SetReadThreadBytesReceivedCallback( -ReadThreadBytesReceived, >GetOutputStream()); -output_comm.StartReadThread(); -join_read_thread = true; -FILE *outfile_handle = -fdopen(pipe.ReleaseWriteFileDescriptor(), "w"); -output_file_sp = std::make_shared(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); -} 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())); -return false; - } - input_file_sp = std::move(nullin.get()); - error_file_sp = output_file_sp = std::make_shared(std::move(nullout.get())); +llvm::Expected> +io_redirect_or_error = +options.GetEnableIO() +? ScriptInterpreterIORedirect::Create(m_debugger, result) +: ScriptInterpreterIORedirect::Create(); +
[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
labath accepted this revision. labath added a comment. This revision is now accepted and ready to land. I think this looks good, though it looks like you have uploaded an partial patch... Comment at: lldb/include/lldb/Interpreter/ScriptInterpreter.h:57-58 private: + friend std::unique_ptr + std::make_unique(); + If that works, I suppose it's fine. But I wouldn't be surprised if this trick backfires on some STL implementations. I think that making an exception for make_unique on classes with private constructors is fine (we already have a bunch of classes like that)... Comment at: lldb/source/Interpreter/ScriptInterpreter.cpp:128-168 if (result) { -m_input_file_sp = debugger.GetInputFileSP(); +redirect->m_input_file_sp = debugger.GetInputFileSP(); Pipe pipe; Status pipe_result = pipe.CreateNew(false); #if defined(_WIN32) lldb::file_t read_file = pipe.GetReadNativeHandle(); Given that none of this fails (though maybe it should), I think it would be cleaner to keep it in the constructor. You can still keep the static factory thing as a wrapper if you want symmetry. Comment at: lldb/source/Interpreter/ScriptInterpreter.cpp:184-190 + std::unique_ptr redirect = + std::make_unique(); + redirect->m_input_file_sp = std::move(nullin.get()); + redirect->m_error_file_sp = redirect->m_output_file_sp = std::make_shared(std::move(nullout.get())); + + return redirect; Similarly, I would find this better as `return std::make_unique(std::move(nullin.get()), std::move(nullout.get()))` (with an appropriate constructor. Mainly because then I don't need to worry about what will the destructor of ScriptInterpreterIORedirect do if we return with the object in an partially initialized state. Repository: rLLDB LLDB CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82396/new/ https://reviews.llvm.org/D82396 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
JDevlieghere updated this revision to Diff 273068. JDevlieghere added a comment. This now has a small function change w.r.t. the error message. Repository: rLLDB LLDB 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 @@ -911,23 +911,23 @@ // 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. -std::unique_ptr io_redirect; -if (options.GetEnableIO()) { - io_redirect = - std::make_unique(m_debugger, result); -} else { - llvm::Error error = llvm::Error::success(); - io_redirect = std::make_unique(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; - } +llvm::Expected> +io_redirect_or_error = +options.GetEnableIO() +? ScriptInterpreterIORedirect::Create(m_debugger, result) +: ScriptInterpreterIORedirect::Create(); +if (!io_redirect_or_error) { + if (result) +result->AppendErrorWithFormatv( +"failed to redirect I/O: {0}\n", +llvm::fmt_consume(io_redirect_or_error.takeError())); + else +llvm::consumeError(io_redirect_or_error.takeError()); + return false; } +ScriptInterpreterIORedirect _redirect = **io_redirect_or_error; + bool success = false; { // WARNING! It's imperative that this RAII scope be as tight as @@ -944,8 +944,8 @@ (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN), Locker::FreeAcquiredLock | Locker::TearDownSession, - io_redirect->GetInputFile(), io_redirect->GetOutputFile(), - io_redirect->GetErrorFile()); + io_redirect.GetInputFile(), io_redirect.GetOutputFile(), + io_redirect.GetErrorFile()); // Find the correct script interpreter dictionary in the main module. PythonDictionary _dict = GetSessionDictionary(); @@ -971,7 +971,7 @@ } } - io_redirect->Flush(); + io_redirect.Flush(); } if (success) Index: lldb/source/Interpreter/ScriptInterpreter.cpp === --- lldb/source/Interpreter/ScriptInterpreter.cpp +++ lldb/source/Interpreter/ScriptInterpreter.cpp @@ -119,12 +119,14 @@ } } -ScriptInterpreterIORedirect::ScriptInterpreterIORedirect( -Debugger , CommandReturnObject *result) -: m_communication("lldb.ScriptInterpreterIORedirect.comm"), - m_disconnect(false) { +llvm::Expected> +ScriptInterpreterIORedirect::Create(Debugger , +CommandReturnObject *result) { + std::unique_ptr redirect = + std::make_unique(); + if (result) { -m_input_file_sp = debugger.GetInputFileSP(); +redirect->m_input_file_sp = debugger.GetInputFileSP(); Pipe pipe; Status pipe_result = pipe.CreateNew(false); @@ -140,15 +142,16 @@ #endif if (conn_up->IsConnected()) { - m_communication.SetConnection(std::move(conn_up)); - m_communication.SetReadThreadBytesReceivedCallback( + redirect->m_communication.SetConnection(std::move(conn_up)); + redirect->m_communication.SetReadThreadBytesReceivedCallback( ReadThreadBytesReceived, >GetOutputStream()); - m_communication.StartReadThread(); - m_disconnect = true; + redirect->m_communication.StartReadThread(); + redirect->m_disconnect = true; FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w"); - m_output_file_sp = std::make_shared(outfile_handle, true); - m_error_file_sp = m_output_file_sp; + redirect->m_output_file_sp = + std::make_shared(outfile_handle, true); + redirect->m_error_file_sp = redirect->m_output_file_sp; if (outfile_handle) ::setbuf(outfile_handle, nullptr); @@ -157,33 +160,40 @@ } } - 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); + if
[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
JDevlieghere marked an inline comment as done. JDevlieghere added inline comments. Comment at: lldb/source/Interpreter/ScriptInterpreter.cpp:171 + if (!nullin) { +error = nullin.takeError(); +return; labath wrote: > I'm pretty sure this will trigger an assertion about overwriting an unchecked > error. One way to handle this would be to wrap the error in an > `ErrorAsOutParameter` object, but I think it's better to replace the > constructor with a static factory function returning an > `Expected`. That's how I did it at first, but I found this more elegant and compact. Maybe the `ErrorAsOutParameter` would tip the scales. I'll change it back to a factory. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82396/new/ https://reviews.llvm.org/D82396 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
labath added a comment. Sounds like a good idea, just the error handling needs to be done carefully. Comment at: lldb/source/Interpreter/ScriptInterpreter.cpp:171 + if (!nullin) { +error = nullin.takeError(); +return; I'm pretty sure this will trigger an assertion about overwriting an unchecked error. One way to handle this would be to wrap the error in an `ErrorAsOutParameter` object, but I think it's better to replace the constructor with a static factory function returning an `Expected`. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82396/new/ https://reviews.llvm.org/D82396 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
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 ) { @@ -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 = 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 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 conn_up( - new ConnectionGenericFile(read_file, true)); -#else - std::unique_ptr conn_up( - new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), - true)); -#endif - if (conn_up->IsConnected()) { -output_comm.SetConnection(std::move(conn_up)); -output_comm.SetReadThreadBytesReceivedCallback( -ReadThreadBytesReceived, >GetOutputStream()); -output_comm.StartReadThread(); -join_read_thread = true; -FILE *outfile_handle = -fdopen(pipe.ReleaseWriteFileDescriptor(), "w"); -output_file_sp = std::make_shared(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(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(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 =
[Lldb-commits] [PATCH] D82396: [lldb/ScriptInterpreter] Extract IO redirection logic and move it out of ScriptInterpreterPython (NFC)
JDevlieghere created this revision. JDevlieghere added reviewers: labath, LLDB. This patch takes the IO redirection logic from ScriptInterpreterPython and moves it into the interpreter library so that it can be used by other script interpreters. I've turned it into a RAII object so that we don't have to worry about cleaning up in the calling code. Repository: rLLDB LLDB 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 ) { @@ -919,75 +911,18 @@ // 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 = 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 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 conn_up( - new ConnectionGenericFile(read_file, true)); -#else - std::unique_ptr conn_up( - new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), - true)); -#endif - if (conn_up->IsConnected()) { -output_comm.SetConnection(std::move(conn_up)); -output_comm.SetReadThreadBytesReceivedCallback( -ReadThreadBytesReceived, >GetOutputStream()); -output_comm.StartReadThread(); -join_read_thread = true; -FILE *outfile_handle = -fdopen(pipe.ReleaseWriteFileDescriptor(), "w"); -output_file_sp = std::make_shared(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(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) { + llvm::Error error = llvm::Error::success(); + io_redirect = std::make_unique(error); + if (error) { result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n", - llvm::fmt_consume(nullin.takeError())); + llvm::fmt_consume(std::move(error))); return false; } - if (!nullout) { -result->AppendErrorWithFormatv("failed to open /dev/null: {0}\n", - llvm::fmt_consume(nullout.takeError())); -return false; - } - input_file_sp = std::move(nullin.get()); - error_file_sp =