diff options
| author | Ilia K <ki.stfu@gmail.com> | 2015-05-07 06:45:42 +0000 |
|---|---|---|
| committer | Ilia K <ki.stfu@gmail.com> | 2015-05-07 06:45:42 +0000 |
| commit | 8913012ee97c8911b4bf95784f70ada3dd94ce44 (patch) | |
| tree | ad957e1bea0b1e79b876fd6d8b5f2115ec9d7267 | |
| parent | 43f7439cf59edd0f4400a12036f8a19745369f3f (diff) | |
| download | bcm5719-llvm-8913012ee97c8911b4bf95784f70ada3dd94ce44.tar.gz bcm5719-llvm-8913012ee97c8911b4bf95784f70ada3dd94ce44.zip | |
Remove quit hook in CMIDriver::DoMainLoop (MI)
Summary:
This patch removes quit hook and fixes 1 bug:
# Fix "quit" hook in CMIDriver::DoMainLoop (MI)
# Fix bug when the handler thread exits without any notification (MI)
# Fix a race condition in CMICmnLLDBDebugger::MonitorSBListenerEvents (MI)
Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/
Reviewers: abidh
Reviewed By: abidh
Subscribers: lldb-commits, abidh
Differential Revision: http://reviews.llvm.org/D9275
llvm-svn: 236702
| -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(); } } } |

