diff options
| -rw-r--r-- | lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp | 45 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MICmnLLDBDebugger.h | 6 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIDriver.cpp | 12 | 
3 files changed, 49 insertions, 14 deletions
| diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp index c16035a6f93..44d788b43b8 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp @@ -222,6 +222,28 @@ CMICmnLLDBDebugger::GetDriver(void) const  }  //++ ------------------------------------------------------------------------------------ +// Details: Wait until all events have been handled. +//          This function works in pair with CMICmnLLDBDebugger::MonitorSBListenerEvents +//          that handles events from queue. When all events were handled and queue is +//          empty the MonitorSBListenerEvents notifies this function that it's ready to +//          go on. To synchronize them the m_mutexEventQueue and +//          m_conditionEventQueueEmpty are used. +// Type:    Method. +// Args:    None. +// Return:  None. +// Throws:  None. +//-- +void +CMICmnLLDBDebugger::WaitForHandleEvent(void) +{ +    std::unique_lock<std::mutex> 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. @@ -642,39 +664,48 @@ CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive)  {      vrbIsAlive = true; +    // Lock the mutex of event queue +    // Note that it should be locked while we are in CMICmnLLDBDebugger::MonitorSBListenerEvents to +    // avoid a race condition with CMICmnLLDBDebugger::WaitForHandleEvent +    std::unique_lock<std::mutex> lock(m_mutexEventQueue); +      lldb::SBEvent event;      const bool bGotEvent = m_lldbListener.GetNextEvent(event); -    if (!bGotEvent || !event.IsValid()) +    if (!bGotEvent)      { +        // Notify that we are finished and unlock the mutex of event queue before sleeping +        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;  }  //++ ------------------------------------------------------------------------------------ diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugger.h b/lldb/tools/lldb-mi/MICmnLLDBDebugger.h index c3cb1497d85..0e66c33939e 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugger.h +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugger.h @@ -10,8 +10,9 @@  #pragma once  // Third party headers -#include <queue> +#include <condition_variable>  #include <map> +#include <mutex>  #include "lldb/API/SBDebugger.h"  #include "lldb/API/SBListener.h"  #include "lldb/API/SBEvent.h" @@ -48,6 +49,7 @@ class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase,      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 @@ class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase,      const CMIUtilString m_constStrThisThreadId;      MapBroadcastClassNameToEventMask_t m_mapBroadcastClassNameToEventMask;      MapIdToEventMask_t m_mapIdToEventMask; +    std::mutex m_mutexEventQueue; +    std::condition_variable m_conditionEventQueueEmpty;  }; diff --git a/lldb/tools/lldb-mi/MIDriver.cpp b/lldb/tools/lldb-mi/MIDriver.cpp index c24f193e894..7d1d9e45b6d 100644 --- a/lldb/tools/lldb-mi/MIDriver.cpp +++ b/lldb/tools/lldb-mi/MIDriver.cpp @@ -536,12 +536,8 @@ CMIDriver::DoMainLoop(void)              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 @@ -549,9 +545,13 @@ CMIDriver::DoMainLoop(void)                      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();              }          }      } | 

