Index: lldb/trunk/include/lldb/Core/Debugger.h =================================================================== --- lldb/trunk/include/lldb/Core/Debugger.h +++ lldb/trunk/include/lldb/Core/Debugger.h @@ -345,9 +345,10 @@ void HandleThreadEvent(const lldb::EventSP &event_sp); - size_t GetProcessSTDOUT(Process *process, Stream *stream); - - size_t GetProcessSTDERR(Process *process, Stream *stream); + // Ensures two threads don't attempt to flush process output in parallel. + std::mutex m_output_flush_mutex; + void FlushProcessOutput(Process &process, bool flush_stdout, + bool flush_stderr); SourceManager::SourceFileCache &GetSourceFileCache() { return m_source_file_cache; Index: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h =================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h +++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h @@ -518,7 +518,7 @@ bool IOHandlerInterrupt(IOHandler &io_handler) override; - size_t GetProcessOutput(); + void GetProcessOutput(); void SetSynchronous(bool value); Index: lldb/trunk/source/Core/Debugger.cpp =================================================================== --- lldb/trunk/source/Core/Debugger.cpp +++ lldb/trunk/source/Core/Debugger.cpp @@ -1252,60 +1252,23 @@ // } } -size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) { - size_t total_bytes = 0; - if (stream == nullptr) - stream = GetOutputFile().get(); - - if (stream) { - // The process has stuff waiting for stdout; get it and write it out to the - // appropriate place. - if (process == nullptr) { - TargetSP target_sp = GetTargetList().GetSelectedTarget(); - if (target_sp) - process = target_sp->GetProcessSP().get(); - } - if (process) { - Status error; - size_t len; - char stdio_buffer[1024]; - while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - stream->Write(stdio_buffer, len); - total_bytes += len; - } - } - stream->Flush(); - } - return total_bytes; -} - -size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) { - size_t total_bytes = 0; - if (stream == nullptr) - stream = GetOutputFile().get(); - - if (stream) { - // The process has stuff waiting for stderr; get it and write it out to the - // appropriate place. - if (process == nullptr) { - TargetSP target_sp = GetTargetList().GetSelectedTarget(); - if (target_sp) - process = target_sp->GetProcessSP().get(); - } - if (process) { - Status error; - size_t len; - char stdio_buffer[1024]; - while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - stream->Write(stdio_buffer, len); - total_bytes += len; - } - } - stream->Flush(); - } - return total_bytes; +void Debugger::FlushProcessOutput(Process &process, bool flush_stdout, + bool flush_stderr) { + const auto &flush = [&](Stream &stream, + size_t (Process::*get)(char *, size_t, Status &)) { + Status error; + size_t len; + char buffer[1024]; + while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0) + stream.Write(buffer, len); + stream.Flush(); + }; + + std::lock_guard guard(m_output_flush_mutex); + if (flush_stdout) + flush(*GetAsyncOutputStream(), &Process::GetSTDOUT); + if (flush_stderr) + flush(*GetAsyncErrorStream(), &Process::GetSTDERR); } // This function handles events that were broadcast by the process. @@ -1345,15 +1308,9 @@ pop_process_io_handler); } - // Now display and STDOUT - if (got_stdout || got_state_changed) { - GetProcessSTDOUT(process_sp.get(), output_stream_sp.get()); - } - - // Now display and STDERR - if (got_stderr || got_state_changed) { - GetProcessSTDERR(process_sp.get(), error_stream_sp.get()); - } + // Now display STDOUT and STDERR + FlushProcessOutput(*process_sp, got_stdout || got_state_changed, + got_stderr || got_state_changed); // Give structured data events an opportunity to display. if (got_structured_data) { Index: lldb/trunk/source/Interpreter/CommandInterpreter.cpp =================================================================== --- lldb/trunk/source/Interpreter/CommandInterpreter.cpp +++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp @@ -2664,32 +2664,14 @@ } } -size_t CommandInterpreter::GetProcessOutput() { - // The process has stuff waiting for stderr; get it and write it out to the - // appropriate place. - char stdio_buffer[1024]; - size_t len; - size_t total_bytes = 0; - Status error; +void CommandInterpreter::GetProcessOutput() { TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget()); - if (target_sp) { - ProcessSP process_sp(target_sp->GetProcessSP()); - if (process_sp) { - while ((len = process_sp->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - size_t bytes_written = len; - m_debugger.GetOutputFile()->Write(stdio_buffer, bytes_written); - total_bytes += len; - } - while ((len = process_sp->GetSTDERR(stdio_buffer, sizeof(stdio_buffer), - error)) > 0) { - size_t bytes_written = len; - m_debugger.GetErrorFile()->Write(stdio_buffer, bytes_written); - total_bytes += len; - } - } - } - return total_bytes; + if (!target_sp) + return; + + if (ProcessSP process_sp = target_sp->GetProcessSP()) + m_debugger.FlushProcessOutput(*process_sp, /*flush_stdout*/ true, + /*flush_stderr*/ true); } void CommandInterpreter::StartHandlingCommand() {