From 58279d1ee1b567e8ca793d6d1eb6e0f1d5e7279e Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 19 Feb 2025 20:32:00 -0800 Subject: [lldb] Synchronize the debuggers output & error streams This patch improves the synchronization of the debugger's output and error streams using two new abstractions: `LockableStreamFile` and `LockedStreamFile`. - `LockableStreamFile` is a wrapper around a `StreamFile` and a mutex. Client cannot use the `StreamFile` without calling `Lock`, which returns a `LockedStreamFile`. - `LockedStreamFile` is an RAII object that locks the stream for the duration of its existence. As long as you hold on to the returned object you are permitted to write to the stream. The destruction of the object automatically flush the output stream. --- .../Python/ScriptInterpreterPython.cpp | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp') diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 9ea5b95..2b92bea 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -7,7 +7,10 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Config.h" +#include "lldb/Host/StreamFile.h" #include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include #if LLDB_ENABLE_PYTHON @@ -489,11 +492,11 @@ def function (frame, bp_loc, internal_dict): break; } - if (instructions) { - StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); - if (output_sp && interactive) { - output_sp->PutCString(instructions); - output_sp->Flush(); + if (instructions && interactive) { + if (LockableStreamFileSP stream_sp = io_handler.GetOutputStreamFileSP()) { + LockedStreamFile locked_stream = stream_sp->Lock(); + locked_stream.PutCString(instructions); + locked_stream.Flush(); } } } @@ -527,10 +530,9 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, bp_options.SetCallback( ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); } else if (!batch_mode) { - StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); - if (error_sp) { - error_sp->Printf("Warning: No command attached to breakpoint.\n"); - error_sp->Flush(); + if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) { + LockedStreamFile locked_stream = error_sp->Lock(); + locked_stream.Printf("Warning: No command attached to breakpoint.\n"); } } } @@ -550,10 +552,9 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, wp_options->SetCallback( ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); } else if (!batch_mode) { - StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); - if (error_sp) { - error_sp->Printf("Warning: No command attached to breakpoint.\n"); - error_sp->Flush(); + if (LockableStreamFileSP error_sp = io_handler.GetErrorStreamFileSP()) { + LockedStreamFile locked_stream = error_sp->Lock(); + locked_stream.Printf("Warning: No command attached to breakpoint.\n"); } } m_active_io_handler = eIOHandlerNone; @@ -680,7 +681,7 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { lldb::FileSP top_in_sp; - lldb::StreamFileSP top_out_sp, top_err_sp; + lldb::LockableStreamFileSP top_out_sp, top_err_sp; if (!in_sp || !out_sp || !err_sp || !*in_sp || !*out_sp || !*err_sp) m_debugger.AdoptTopIOHandlerFilesIfInvalid(top_in_sp, top_out_sp, top_err_sp); @@ -696,12 +697,14 @@ bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags, if (!SetStdHandle(out_sp, "stdout", m_saved_stdout, "w")) { if (top_out_sp) - SetStdHandle(top_out_sp->GetFileSP(), "stdout", m_saved_stdout, "w"); + SetStdHandle(top_out_sp->GetUnlockedFileSP(), "stdout", m_saved_stdout, + "w"); } if (!SetStdHandle(err_sp, "stderr", m_saved_stderr, "w")) { if (top_err_sp) - SetStdHandle(top_err_sp->GetFileSP(), "stderr", m_saved_stderr, "w"); + SetStdHandle(top_err_sp->GetUnlockedFileSP(), "stderr", m_saved_stderr, + "w"); } } -- cgit v1.1