summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp45
-rw-r--r--lldb/tools/lldb-mi/MICmnLLDBDebugger.h6
-rw-r--r--lldb/tools/lldb-mi/MIDriver.cpp12
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();
}
}
}
OpenPOWER on IntegriCloud