1 //===-- MICmnLLDBDebugger.cpp -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Third party headers:
11 #include "lldb/API/SBTarget.h"
12 #include "lldb/API/SBThread.h"
13 #include "lldb/API/SBProcess.h"
14 #include "lldb/API/SBCommandInterpreter.h"
17 #include "MICmnLLDBDebugger.h"
18 #include "MICmnResources.h"
20 #include "MIDriverBase.h"
21 #include "MICmnThreadMgrStd.h"
22 #include "MICmnLLDBDebuggerHandleEvents.h"
23 #include "MICmnLLDBDebugSessionInfo.h"
24 #include "MIUtilSingletonHelper.h"
26 //++ ------------------------------------------------------------------------------------
27 // Details: CMICmnLLDBDebugger constructor.
33 CMICmnLLDBDebugger::CMICmnLLDBDebugger(void)
34 : m_constStrThisThreadId("MI debugger event")
38 //++ ------------------------------------------------------------------------------------
39 // Details: CMICmnLLDBDebugger destructor.
45 CMICmnLLDBDebugger::~CMICmnLLDBDebugger(void)
50 //++ ------------------------------------------------------------------------------------
51 // Details: Initialize resources for *this debugger object.
54 // Return: MIstatus::success - Functionality succeeded.
55 // MIstatus::failure - Functionality failed.
59 CMICmnLLDBDebugger::Initialize(void)
61 m_clientUsageRefCnt++;
64 return MIstatus::success;
66 bool bOk = MIstatus::success;
68 ClrErrorDescription();
70 if (m_pClientDriver == nullptr)
73 errMsg = MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER);
76 // Note initialization order is important here as some resources depend on previous
77 MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
78 MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
79 MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg);
80 MI::ModuleInit<CMICmnLLDBDebuggerHandleEvents>(IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg);
81 MI::ModuleInit<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg);
83 // Note order is important here!
85 lldb::SBDebugger::Initialize();
86 if (bOk && !InitSBDebugger())
91 errMsg += GetErrorDescription().c_str();
93 if (bOk && !InitSBListener())
98 errMsg += GetErrorDescription().c_str();
100 bOk = bOk && InitStdStreams();
102 m_bInitialized = bOk;
104 if (!bOk && !HaveErrorDescription())
106 CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str()));
107 SetErrorDescription(strInitError);
113 //++ ------------------------------------------------------------------------------------
114 // Details: Release resources for *this debugger object.
117 // Return: MIstatus::success - Functionality succeeded.
118 // MIstatus::failure - Functionality failed.
122 CMICmnLLDBDebugger::Shutdown(void)
124 if (--m_clientUsageRefCnt > 0)
125 return MIstatus::success;
128 return MIstatus::success;
130 m_bInitialized = false;
132 ClrErrorDescription();
134 bool bOk = MIstatus::success;
135 CMIUtilString errMsg;
137 // Explicitly delete the remote target in case MI needs to exit prematurely otherwise
138 // LLDB debugger may hang in its Destroy() fn waiting on events
139 lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget();
140 m_lldbDebugger.DeleteTarget(sbTarget);
142 // Debug: May need this but does seem to work without it so commented out the fudge 19/06/2014
143 // It appears we need to wait as hang does not occur when hitting a debug breakpoint here
144 // const std::chrono::milliseconds time( 1000 );
145 // std::this_thread::sleep_for( time );
147 lldb::SBDebugger::Destroy(m_lldbDebugger);
148 lldb::SBDebugger::Terminate();
149 m_pClientDriver = nullptr;
150 m_mapBroadcastClassNameToEventMask.clear();
151 m_mapIdToEventMask.clear();
153 // Note shutdown order is important here
154 MI::ModuleShutdown<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg);
155 MI::ModuleShutdown<CMICmnLLDBDebuggerHandleEvents>(IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg);
156 MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg);
157 MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg);
158 MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg);
162 SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_LLDBDEBUGGER), errMsg.c_str());
165 return MIstatus::success;
168 //++ ------------------------------------------------------------------------------------
169 // Details: Return the LLDB debugger instance created for this debug session.
172 // Return: lldb::SBDebugger & - LLDB debugger object reference.
176 CMICmnLLDBDebugger::GetTheDebugger(void)
178 return m_lldbDebugger;
181 //++ ------------------------------------------------------------------------------------
182 // Details: Return the LLDB listener instance created for this debug session.
185 // Return: lldb::SBListener & - LLDB listener object reference.
189 CMICmnLLDBDebugger::GetTheListener(void)
191 return m_lldbListener;
194 //++ ------------------------------------------------------------------------------------
195 // Details: Set the client driver that wants to use *this LLDB debugger. Call this function
196 // prior to Initialize().
198 // Args: vClientDriver - (R) A driver.
199 // Return: MIstatus::success - Functionality succeeded.
200 // MIstatus::failure - Functionality failed.
204 CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver)
206 m_pClientDriver = const_cast<CMIDriverBase *>(&vClientDriver);
208 return MIstatus::success;
211 //++ ------------------------------------------------------------------------------------
212 // Details: Get the client driver that is use *this LLDB debugger.
214 // Args: vClientDriver - (R) A driver.
215 // Return: CMIDriverBase & - A driver instance.
219 CMICmnLLDBDebugger::GetDriver(void) const
221 return *m_pClientDriver;
224 //++ ------------------------------------------------------------------------------------
225 // Details: Wait until all events have been handled.
226 // This function works in pair with CMICmnLLDBDebugger::MonitorSBListenerEvents
227 // that handles events from queue. When all events were handled and queue is
228 // empty the MonitorSBListenerEvents notifies this function that it's ready to
229 // go on. To synchronize them the m_mutexEventQueue and
230 // m_conditionEventQueueEmpty are used.
237 CMICmnLLDBDebugger::WaitForHandleEvent(void)
239 std::unique_lock<std::mutex> lock(m_mutexEventQueue);
242 if (ThreadIsActive() && m_lldbListener.PeekAtNextEvent(event))
243 m_conditionEventQueueEmpty.wait(lock);
246 //++ ------------------------------------------------------------------------------------
247 // Details: Check if need to rebroadcast stop event. This function will return true if
248 // debugger is in synchronouse mode. In such case the
249 // CMICmnLLDBDebugger::RebroadcastStopEvent should be called to rebroadcast
250 // a new stop event (if any).
253 // Return: bool - True = Need to rebroadcast stop event, false = otherwise.
257 CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent(void)
259 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
260 if (!rSessionInfo.GetDebugger().GetAsync())
262 const bool include_expression_stops = false;
263 m_nLastStopId = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetStopID(include_expression_stops);
270 //++ ------------------------------------------------------------------------------------
271 // Details: Rebroadcast stop event if needed. This function should be called only if the
272 // CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() returned true.
279 CMICmnLLDBDebugger::RebroadcastStopEvent(void)
281 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
282 const bool include_expression_stops = false;
283 const uint32_t nStopId = process.GetStopID(include_expression_stops);
284 if (m_nLastStopId != nStopId)
286 lldb::SBEvent event = process.GetStopEventForStopID(nStopId);
287 process.GetBroadcaster().BroadcastEvent(event);
291 //++ ------------------------------------------------------------------------------------
292 // Details: Initialize the LLDB Debugger object.
295 // Return: MIstatus::success - Functionality succeeded.
296 // MIstatus::failure - Functionality failed.
300 CMICmnLLDBDebugger::InitSBDebugger(void)
302 m_lldbDebugger = lldb::SBDebugger::Create(false);
303 if (!m_lldbDebugger.IsValid())
305 SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER));
306 return MIstatus::failure;
309 m_lldbDebugger.GetCommandInterpreter().SetPromptOnQuit(false);
311 return MIstatus::success;
314 //++ ------------------------------------------------------------------------------------
315 // Details: Set the LLDB Debugger's std in, err and out streams. (Not implemented left
316 // here for reference. Was called in the CMICmnLLDBDebugger::Initialize() )
319 // Return: MIstatus::success - Functionality succeeded.
320 // MIstatus::failure - Functionality failed.
324 CMICmnLLDBDebugger::InitStdStreams(void)
326 // This is not required when operating the MI driver's code as it has its own
327 // streams. Setting the Stdin for the lldbDebugger especially on LINUX will cause
328 // another thread to run and partially consume stdin data meant for MI stdin handler
329 // m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false );
330 // m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false );
331 // m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false );
333 return MIstatus::success;
336 //++ ------------------------------------------------------------------------------------
337 // Details: Set up the events from the SBDebugger's we would like to listen to.
340 // Return: MIstatus::success - Functionality succeeded.
341 // MIstatus::failure - Functionality failed.
345 CMICmnLLDBDebugger::InitSBListener(void)
347 m_lldbListener = m_lldbDebugger.GetListener();
348 if (!m_lldbListener.IsValid())
350 SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER));
351 return MIstatus::failure;
354 const CMIUtilString strDbgId("CMICmnLLDBDebugger1");
355 MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged | lldb::SBTarget::eBroadcastBitModulesLoaded |
356 lldb::SBTarget::eBroadcastBitModulesUnloaded | lldb::SBTarget::eBroadcastBitWatchpointChanged |
357 lldb::SBTarget::eBroadcastBitSymbolsLoaded;
358 bool bOk = RegisterForEvent(strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()), eventMask);
360 eventMask = lldb::SBThread::eBroadcastBitStackChanged;
361 bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBThread::GetBroadcasterClassName()), eventMask);
363 eventMask = lldb::SBProcess::eBroadcastBitStateChanged | lldb::SBProcess::eBroadcastBitInterrupt |
364 lldb::SBProcess::eBroadcastBitSTDOUT | lldb::SBProcess::eBroadcastBitSTDERR | lldb::SBProcess::eBroadcastBitProfileData;
365 bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()), eventMask);
367 eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit |
368 lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
369 lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData;
370 bOk = bOk && RegisterForEvent(strDbgId, m_lldbDebugger.GetCommandInterpreter().GetBroadcaster(), eventMask);
375 //++ ------------------------------------------------------------------------------------
376 // Details: Register with the debugger, the SBListener, the type of events you are interested
377 // in. Others, like commands, may have already set the mask.
379 // Args: vClientName - (R) ID of the client who wants these events set.
380 // vBroadcasterClass - (R) The SBBroadcaster's class name.
381 // vEventMask - (R) The mask of events to listen for.
382 // Return: MIstatus::success - Functionality succeeded.
383 // MIstatus::failure - Functionality failed.
387 CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask)
389 MIuint existingMask = 0;
390 if (!BroadcasterGetMask(vBroadcasterClass, existingMask))
391 return MIstatus::failure;
393 if (!ClientSaveMask(vClientName, vBroadcasterClass, vEventMask))
394 return MIstatus::failure;
396 const char *pBroadCasterName = vBroadcasterClass.c_str();
397 MIuint eventMask = vEventMask;
398 eventMask += existingMask;
399 const MIuint result = m_lldbListener.StartListeningForEventClass(m_lldbDebugger, pBroadCasterName, eventMask);
402 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadCasterName));
403 return MIstatus::failure;
406 return BroadcasterSaveMask(vBroadcasterClass, eventMask);
409 //++ ------------------------------------------------------------------------------------
410 // Details: Register with the debugger, the SBListener, the type of events you are interested
411 // in. Others, like commands, may have already set the mask.
413 // Args: vClientName - (R) ID of the client who wants these events set.
414 // vBroadcaster - (R) An SBBroadcaster's derived class.
415 // vEventMask - (R) The mask of events to listen for.
416 // Return: MIstatus::success - Functionality succeeded.
417 // MIstatus::failure - Functionality failed.
421 CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, const MIuint vEventMask)
423 const char *pBroadcasterName = vBroadcaster.GetName();
424 if (pBroadcasterName == nullptr)
426 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME), MIRSRC(IDS_WORD_INVALIDNULLPTR)));
427 return MIstatus::failure;
429 CMIUtilString broadcasterName(pBroadcasterName);
430 if (broadcasterName.length() == 0)
432 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROARDCASTER_NAME), MIRSRC(IDS_WORD_INVALIDEMPTY)));
433 return MIstatus::failure;
436 MIuint existingMask = 0;
437 if (!BroadcasterGetMask(broadcasterName, existingMask))
438 return MIstatus::failure;
440 if (!ClientSaveMask(vClientName, broadcasterName, vEventMask))
441 return MIstatus::failure;
443 MIuint eventMask = vEventMask;
444 eventMask += existingMask;
445 const MIuint result = m_lldbListener.StartListeningForEvents(vBroadcaster, eventMask);
448 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadcasterName));
449 return MIstatus::failure;
452 return BroadcasterSaveMask(broadcasterName, eventMask);
455 //++ ------------------------------------------------------------------------------------
456 // Details: Unregister with the debugger, the SBListener, the type of events you are no
457 // longer interested in. Others, like commands, may still remain interested so
458 // an event may not necessarily be stopped.
460 // Args: vClientName - (R) ID of the client who no longer requires these events.
461 // vBroadcasterClass - (R) The SBBroadcaster's class name.
462 // Return: MIstatus::success - Functionality succeeded.
463 // MIstatus::failure - Functionality failed.
467 CMICmnLLDBDebugger::UnregisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass)
469 MIuint clientsEventMask = 0;
470 if (!ClientGetTheirMask(vClientName, vBroadcasterClass, clientsEventMask))
471 return MIstatus::failure;
472 if (!ClientRemoveTheirMask(vClientName, vBroadcasterClass))
473 return MIstatus::failure;
475 const MIuint otherClientsEventMask = ClientGetMaskForAllClients(vBroadcasterClass);
476 MIuint newEventMask = 0;
477 for (MIuint i = 0; i < 32; i++)
479 const MIuint bit = 1 << i;
480 const MIuint clientBit = bit & clientsEventMask;
481 const MIuint othersBit = bit & otherClientsEventMask;
482 if ((clientBit != 0) && (othersBit == 0))
484 newEventMask += clientBit;
488 const char *pBroadCasterName = vBroadcasterClass.c_str();
489 if (!m_lldbListener.StopListeningForEventClass(m_lldbDebugger, pBroadCasterName, newEventMask))
491 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STOPLISTENER), vClientName.c_str(), pBroadCasterName));
492 return MIstatus::failure;
495 return BroadcasterSaveMask(vBroadcasterClass, otherClientsEventMask);
498 //++ ------------------------------------------------------------------------------------
499 // Details: Given the SBBroadcaster class name retrieve it's current event mask.
501 // Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
502 // vEventMask - (W) The mask of events to listen for.
503 // Return: MIstatus::success - Functionality succeeded.
504 // MIstatus::failure - Functionality failed.
508 CMICmnLLDBDebugger::BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) const
512 if (vBroadcasterClass.empty())
514 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str()));
515 return MIstatus::failure;
518 const MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass);
519 if (it != m_mapBroadcastClassNameToEventMask.end())
521 vwEventMask = (*it).second;
524 return MIstatus::success;
527 //++ ------------------------------------------------------------------------------------
528 // Details: Remove the event mask for the specified SBBroadcaster class name.
530 // Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
531 // Return: MIstatus::success - Functionality succeeded.
532 // MIstatus::failure - Functionality failed.
536 CMICmnLLDBDebugger::BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass)
538 MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass);
539 if (it != m_mapBroadcastClassNameToEventMask.end())
541 m_mapBroadcastClassNameToEventMask.erase(it);
544 return MIstatus::success;
547 //++ ------------------------------------------------------------------------------------
548 // Details: Given the SBBroadcaster class name save it's current event mask.
550 // Args: vBroadcasterClass - (R) The SBBroadcaster's class name.
551 // vEventMask - (R) The mask of events to listen for.
552 // Return: MIstatus::success - Functionality succeeded.
553 // MIstatus::failure - Functionality failed.
557 CMICmnLLDBDebugger::BroadcasterSaveMask(const CMIUtilString &vBroadcasterClass, const MIuint vEventMask)
559 if (vBroadcasterClass.empty())
561 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str()));
562 return MIstatus::failure;
565 BroadcasterRemoveMask(vBroadcasterClass);
566 MapPairBroadcastClassNameToEventMask_t pr(vBroadcasterClass, vEventMask);
567 m_mapBroadcastClassNameToEventMask.insert(pr);
569 return MIstatus::success;
572 //++ ------------------------------------------------------------------------------------
573 // Details: Iterate all the clients who have registered event masks against particular
574 // SBBroadcasters and build up the mask that is for all of them.
576 // Args: vBroadcasterClass - (R) The broadcaster to retrieve the mask for.
577 // Return: MIuint - Event mask.
581 CMICmnLLDBDebugger::ClientGetMaskForAllClients(const CMIUtilString &vBroadcasterClass) const
584 MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin();
585 while (it != m_mapIdToEventMask.end())
587 const CMIUtilString &rId((*it).first);
588 if (rId.find(vBroadcasterClass.c_str()) != std::string::npos)
590 const MIuint clientsMask = (*it).second;
601 //++ ------------------------------------------------------------------------------------
602 // Details: Given the client save its particular event requirements.
604 // Args: vClientName - (R) The Client's unique ID.
605 // vBroadcasterClass - (R) The SBBroadcaster's class name targeted for the events.
606 // vEventMask - (R) The mask of events to listen for.
607 // Return: MIstatus::success - Functionality succeeded.
608 // MIstatus::failure - Functionality failed.
612 CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask)
614 if (vClientName.empty())
616 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
617 return MIstatus::failure;
620 CMIUtilString strId(vBroadcasterClass);
621 strId += vClientName;
623 ClientRemoveTheirMask(vClientName, vBroadcasterClass);
624 MapPairIdToEventMask_t pr(strId, vEventMask);
625 m_mapIdToEventMask.insert(pr);
627 return MIstatus::success;
630 //++ ------------------------------------------------------------------------------------
631 // Details: Given the client remove it's particular event requirements.
633 // Args: vClientName - (R) The Client's unique ID.
634 // vBroadcasterClass - (R) The SBBroadcaster's class name.
635 // Return: MIstatus::success - Functionality succeeded.
636 // MIstatus::failure - Functionality failed.
640 CMICmnLLDBDebugger::ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass)
642 if (vClientName.empty())
644 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
645 return MIstatus::failure;
648 CMIUtilString strId(vBroadcasterClass);
649 strId += vClientName;
651 const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId);
652 if (it != m_mapIdToEventMask.end())
654 m_mapIdToEventMask.erase(it);
657 return MIstatus::success;
660 //++ ------------------------------------------------------------------------------------
661 // Details: Retrieve the client's event mask used for on a particular SBBroadcaster.
663 // Args: vClientName - (R) The Client's unique ID.
664 // vBroadcasterClass - (R) The SBBroadcaster's class name.
665 // vwEventMask - (W) The client's mask.
666 // Return: MIstatus::success - Functionality succeeded.
667 // MIstatus::failure - Functionality failed.
671 CMICmnLLDBDebugger::ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask)
675 if (vClientName.empty())
677 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str()));
678 return MIstatus::failure;
681 CMIUtilString strId(vBroadcasterClass.c_str());
682 strId += vClientName;
684 const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId);
685 if (it != m_mapIdToEventMask.end())
687 vwEventMask = (*it).second;
690 SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED), vClientName.c_str()));
692 return MIstatus::failure;
695 //++ ------------------------------------------------------------------------------------
696 // Details: Momentarily wait for an events being broadcast and inspect those that do
697 // come this way. Check if the target should exit event if so start shutting
698 // down this thread and the application. Any other events pass on to the
699 // Out-of-band handler to further determine what kind of event arrived.
700 // This function runs in the thread "MI debugger event".
702 // Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true = continue.
703 // Return: MIstatus::success - Functional succeeded.
704 // MIstatus::failure - Functional failed.
708 CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive)
712 // Lock the mutex of event queue
713 // Note that it should be locked while we are in CMICmnLLDBDebugger::MonitorSBListenerEvents to
714 // avoid a race condition with CMICmnLLDBDebugger::WaitForHandleEvent
715 std::unique_lock<std::mutex> lock(m_mutexEventQueue);
718 const bool bGotEvent = m_lldbListener.GetNextEvent(event);
721 // Notify that we are finished and unlock the mutex of event queue before sleeping
722 m_conditionEventQueueEmpty.notify_one();
725 // Wait a bit to reduce CPU load
726 const std::chrono::milliseconds time(1);
727 std::this_thread::sleep_for(time);
728 return MIstatus::success;
730 assert(event.IsValid());
731 assert(event.GetBroadcaster().IsValid());
734 m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", event.GetBroadcasterClass()));
736 bool bHandledEvent = false;
739 // Lock Mutex before handling events so that we don't disturb a running cmd
740 CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex());
741 bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent);
746 const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), event.GetBroadcasterClass()));
747 m_pLog->WriteLog(msg);
751 m_pLog->WriteLog(CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription());
753 return MIstatus::success;
756 //++ ------------------------------------------------------------------------------------
757 // Details: The main worker method for this thread.
759 // Args: vrbIsAlive - (W) True = *this thread is working, false = thread has exited.
760 // Return: MIstatus::success - Functional succeeded.
761 // MIstatus::failure - Functional failed.
765 CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive)
767 return MonitorSBListenerEvents(vrbIsAlive);
770 //++ ------------------------------------------------------------------------------------
771 // Details: Let this thread clean up after itself.
774 // Return: MIstatus::success - Functionality succeeded.
775 // MIstatus::failure - Functionality failed.
779 CMICmnLLDBDebugger::ThreadFinish(void)
781 return MIstatus::success;
784 //++ ------------------------------------------------------------------------------------
785 // Details: Retrieve *this thread object's name.
788 // Return: CMIUtilString & - Text.
791 const CMIUtilString &
792 CMICmnLLDBDebugger::ThreadGetName(void) const
794 return m_constStrThisThreadId;