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;
// }
}
-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<std::mutex> 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.
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) {
}
}
-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() {