Index: tools/lldb-mi/MICmnLLDBDebugger.h =================================================================== --- tools/lldb-mi/MICmnLLDBDebugger.h +++ tools/lldb-mi/MICmnLLDBDebugger.h @@ -10,8 +10,9 @@ #pragma once // Third party headers -#include +#include #include +#include #include "lldb/API/SBDebugger.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBEvent.h" @@ -48,6 +49,7 @@ CMIDriverBase &GetDriver(void) const; lldb::SBDebugger &GetTheDebugger(void); lldb::SBListener &GetTheListener(void); + void WaitForHandleEvent(void); // MI Commands can use these functions to listen for events they require bool RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); @@ -106,4 +108,6 @@ const CMIUtilString m_constStrThisThreadId; MapBroadcastClassNameToEventMask_t m_mapBroadcastClassNameToEventMask; MapIdToEventMask_t m_mapIdToEventMask; + std::mutex m_mutexEventQueue; + std::condition_variable m_conditionEventQueueEmpty; }; Index: tools/lldb-mi/MICmnLLDBDebugger.cpp =================================================================== --- tools/lldb-mi/MICmnLLDBDebugger.cpp +++ tools/lldb-mi/MICmnLLDBDebugger.cpp @@ -222,6 +222,23 @@ } //++ ------------------------------------------------------------------------------------ +// Details: Wait until all events have been handled. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +void +CMICmnLLDBDebugger::WaitForHandleEvent(void) +{ + std::unique_lock lock(m_mutexEventQueue); + + lldb::SBEvent event; + if (ThreadIsActive() && m_lldbListener.PeekAtNextEvent(event)) + m_conditionEventQueueEmpty.wait(lock); +} + +//++ ------------------------------------------------------------------------------------ // Details: Initialize the LLDB Debugger object. // Type: Method. // Args: None. @@ -643,38 +660,44 @@ vrbIsAlive = true; lldb::SBEvent event; - const bool bGotEvent = m_lldbListener.GetNextEvent(event); - if (!bGotEvent || !event.IsValid()) { - const std::chrono::milliseconds time(1); - std::this_thread::sleep_for(time); - return MIstatus::success; + std::unique_lock lock(m_mutexEventQueue); + + const bool bGotEvent = m_lldbListener.GetNextEvent(event); + if (!bGotEvent) + { + m_conditionEventQueueEmpty.notify_one(); + lock.unlock(); + // Wait a bit to reduce CPU load + const std::chrono::milliseconds time(1); + std::this_thread::sleep_for(time); + return MIstatus::success; + } } - if (!event.GetBroadcaster().IsValid()) - return MIstatus::success; + assert(event.IsValid()); + assert(event.GetBroadcaster().IsValid()); // Debugging m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", event.GetBroadcasterClass())); bool bHandledEvent = false; - bool bOk = false; { // Lock Mutex before handling events so that we don't disturb a running cmd CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent); } + if (!bHandledEvent) { const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), event.GetBroadcasterClass())); m_pLog->WriteLog(msg); } + if (!bOk) - { m_pLog->WriteLog(CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription()); - } - return bOk; + return MIstatus::success; } //++ ------------------------------------------------------------------------------------ Index: tools/lldb-mi/MIDriver.cpp =================================================================== --- tools/lldb-mi/MIDriver.cpp +++ tools/lldb-mi/MIDriver.cpp @@ -538,12 +538,8 @@ CMIUtilString lineText(pCmd); if (!lineText.empty ()) { - if (lineText == "quit") - { - // We want to be exiting when receiving a quit command - m_bExitApp = true; - break; - } + // Check that the handler thread is alive (otherwise we stuck here) + assert(CMICmnLLDBDebugger::Instance().ThreadIsActive()); { // Lock Mutex before processing commands so that we don't disturb an event @@ -551,9 +547,13 @@ CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); bOk = InterpretCommand(lineText); } + // Draw prompt if desired if (bOk && m_rStdin.GetEnablePrompt()) bOk = m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt()); + + // Wait while the handler thread handles incoming events + CMICmnLLDBDebugger::Instance().WaitForHandleEvent(); } } }