Index: lldb/include/lldb/Interpreter/ScriptInterpreter.h =================================================================== --- lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -37,11 +37,12 @@ class ScriptInterpreterIORedirect { public: /// Create an IO redirect with /dev/null as input, output and error file. - ScriptInterpreterIORedirect(llvm::Error &error); + static llvm::Expected> Create(); /// 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); + static llvm::Expected> + Create(Debugger &debugger, CommandReturnObject *result); ~ScriptInterpreterIORedirect(); @@ -53,6 +54,11 @@ void Flush(); private: + friend std::unique_ptr + std::make_unique(); + + ScriptInterpreterIORedirect(); + lldb::FileSP m_input_file_sp; lldb::StreamFileSP m_output_file_sp; lldb::StreamFileSP m_error_file_sp; Index: lldb/source/Interpreter/ScriptInterpreter.cpp =================================================================== --- lldb/source/Interpreter/ScriptInterpreter.cpp +++ lldb/source/Interpreter/ScriptInterpreter.cpp @@ -119,12 +119,14 @@ } } -ScriptInterpreterIORedirect::ScriptInterpreterIORedirect( - Debugger &debugger, CommandReturnObject *result) - : m_communication("lldb.ScriptInterpreterIORedirect.comm"), - m_disconnect(false) { +llvm::Expected> +ScriptInterpreterIORedirect::Create(Debugger &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, &result->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 (!redirect->m_input_file_sp || !redirect->m_output_file_sp || + !redirect->m_error_file_sp) + debugger.AdoptTopIOHandlerFilesIfInvalid(redirect->m_input_file_sp, + redirect->m_output_file_sp, + redirect->m_error_file_sp); + + return redirect; } -ScriptInterpreterIORedirect::ScriptInterpreterIORedirect(llvm::Error &error) - : m_communication("lldb.ScriptInterpreterIORedirect.comm"), - m_disconnect(false) { +llvm::Expected> +ScriptInterpreterIORedirect::Create() { auto nullin = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL), File::eOpenOptionRead); - if (!nullin) { - error = nullin.takeError(); - return; - } + if (!nullin) + return nullin.takeError(); auto nullout = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL), File::eOpenOptionWrite); - if (!nullout) { - error = nullout.takeError(); - return; - } + if (!nullout) + return nullin.takeError(); - m_input_file_sp = std::move(nullin.get()); - m_error_file_sp = m_output_file_sp = + 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; } +ScriptInterpreterIORedirect::ScriptInterpreterIORedirect() + : m_communication("lldb.ScriptInterpreterIORedirect.comm"), + m_disconnect(false) {} + void ScriptInterpreterIORedirect::Flush() { if (m_output_file_sp) m_output_file_sp->Flush(); 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 &io_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 &session_dict = GetSessionDictionary(); @@ -971,7 +971,7 @@ } } - io_redirect->Flush(); + io_redirect.Flush(); } if (success)