Index: lldb/include/lldb/Core/Debugger.h =================================================================== --- lldb/include/lldb/Core/Debugger.h +++ lldb/include/lldb/Core/Debugger.h @@ -191,13 +191,11 @@ lldb::StreamFileSP &err); void PushIOHandler(const lldb::IOHandlerSP &reader_sp, - bool cancel_top_handler = true); + bool cancel_top_handler = true, + bool asynchronous_if_needed = false); bool PopIOHandler(const lldb::IOHandlerSP &reader_sp); - // Synchronously run an input reader until it is done - void RunIOHandler(const lldb::IOHandlerSP &reader_sp); - bool IsTopIOHandler(const lldb::IOHandlerSP &reader_sp); bool CheckTopIOHandlerTypes(IOHandler::Type top_type, @@ -403,6 +401,9 @@ m_script_interpreters; IOHandlerStack m_input_reader_stack; + std::mutex m_synchronous_reader_mutex; + std::unique_lock m_synchronous_reader_lock; + llvm::StringMap> m_log_streams; std::shared_ptr m_log_callback_stream_sp; ConstString m_instance_name; Index: lldb/source/Core/Debugger.cpp =================================================================== --- lldb/source/Core/Debugger.cpp +++ lldb/source/Core/Debugger.cpp @@ -708,9 +708,10 @@ m_source_manager_up(), m_source_file_cache(), m_command_interpreter_up( std::make_unique(*this, false)), - m_input_reader_stack(), m_instance_name(), m_loaded_plugins(), - m_event_handler_thread(), m_io_handler_thread(), - m_sync_broadcaster(nullptr, "lldb.debugger.sync"), + m_input_reader_stack(), + m_synchronous_reader_lock(m_synchronous_reader_mutex, std::defer_lock), + m_instance_name(), m_loaded_plugins(), m_event_handler_thread(), + m_io_handler_thread(), m_sync_broadcaster(nullptr, "lldb.debugger.sync"), m_forward_listener_sp(), m_clear_once() { char instance_cstr[256]; snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); @@ -895,6 +896,11 @@ } void Debugger::ExecuteIOHandlers() { + // Prevent anyone from executing the IO handlers synchronously while they're + // running here. + std::lock_guard> guard( + m_synchronous_reader_lock); + while (true) { IOHandlerSP reader_sp(m_input_reader_stack.Top()); if (!reader_sp) @@ -941,28 +947,6 @@ return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); } -void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) { - PushIOHandler(reader_sp); - - IOHandlerSP top_reader_sp = reader_sp; - while (top_reader_sp) { - top_reader_sp->Run(); - - if (top_reader_sp.get() == reader_sp.get()) { - if (PopIOHandler(reader_sp)) - break; - } - - while (true) { - top_reader_sp = m_input_reader_stack.Top(); - if (top_reader_sp && top_reader_sp->GetIsDone()) - PopIOHandler(top_reader_sp); - else - break; - } - } -} - void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out, StreamFileSP &err) { // Before an IOHandler runs, it must have in/out/err streams. This function @@ -1005,7 +989,8 @@ } void Debugger::PushIOHandler(const IOHandlerSP &reader_sp, - bool cancel_top_handler) { + bool cancel_top_handler, + bool asynchronous_if_needed) { if (!reader_sp) return; @@ -1029,6 +1014,12 @@ if (cancel_top_handler) top_reader_sp->Cancel(); } + + // Support running the IO handlers synchronously on the current thread if + // they aren't running yet. + if (asynchronous_if_needed && !m_synchronous_reader_lock.owns_lock()) { + ExecuteIOHandlers(); + } } bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) { Index: lldb/source/Interpreter/CommandInterpreter.cpp =================================================================== --- lldb/source/Interpreter/CommandInterpreter.cpp +++ lldb/source/Interpreter/CommandInterpreter.cpp @@ -1854,7 +1854,7 @@ IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger, message, default_answer); IOHandlerSP io_handler_sp(confirm); - m_debugger.RunIOHandler(io_handler_sp); + m_debugger.PushIOHandler(io_handler_sp); return confirm->GetResponse(); } @@ -2477,7 +2477,11 @@ m_command_source_depth++; - debugger.RunIOHandler(io_handler_sp); + const bool cancel_top_handler = true; + const bool asynchronous_if_needed = true; + debugger.PushIOHandler(io_handler_sp, cancel_top_handler, + asynchronous_if_needed); + if (!m_command_source_flags.empty()) m_command_source_flags.pop_back(); m_command_source_depth--;