diff options
| author | Hafiz Abid Qadeer <hafiz_abid@mentor.com> | 2015-02-20 10:20:05 +0000 |
|---|---|---|
| committer | Hafiz Abid Qadeer <hafiz_abid@mentor.com> | 2015-02-20 10:20:05 +0000 |
| commit | 6d87a9c09e3b44a8bba2742869f5200f796c39f0 (patch) | |
| tree | 58dcd9c496ae9bc98f50f448a02994647a9a2a94 | |
| parent | 846de99fbd2024dd8c0626408c8f3e3211b4cf0d (diff) | |
| download | bcm5719-llvm-6d87a9c09e3b44a8bba2742869f5200f796c39f0.tar.gz bcm5719-llvm-6d87a9c09e3b44a8bba2742869f5200f796c39f0.zip | |
Reduce number of threads in lldb-mi.
LLDB-mi have 3 threads.
1. Wait for input.
2. Process commands.
3. Process events.
This revision merges 1 & 2. Same thread waits on input and then process the
command. This way, no synchronization is needed between first and 2nd. Also it is
easy to check when to exit.
A lot of code will redundant and will be cleaned up gradually.
All lldb-mi tests pass with gcc and clang as test compiler. Also did minimal testing
on command line and works ok. The "quit" and "-gdb-exit" command close the application
without needing any further return.
Reviewed in http://reviews.llvm.org/D7746.
llvm-svn: 230003
| -rw-r--r-- | lldb/tools/lldb-mi/Driver.h | 1 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MICmnStreamStdin.cpp | 34 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MICmnStreamStdin.h | 4 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIDriver.cpp | 199 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIDriver.h | 8 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIDriverMain.cpp | 13 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIDriverMgr.cpp | 16 | ||||
| -rw-r--r-- | lldb/tools/lldb-mi/MIDriverMgr.h | 2 |
8 files changed, 105 insertions, 172 deletions
diff --git a/lldb/tools/lldb-mi/Driver.h b/lldb/tools/lldb-mi/Driver.h index 5bc97383a0c..cd9fc043ea4 100644 --- a/lldb/tools/lldb-mi/Driver.h +++ b/lldb/tools/lldb-mi/Driver.h @@ -64,6 +64,7 @@ class Driver : public lldb::SBBroadcaster, public CMIDriverBase, public CMIDrive virtual bool SetDriverParent(const CMIDriverBase &vrOtherDriver); virtual const CMIUtilString &GetDriverName(void) const; virtual const CMIUtilString &GetDriverId(void) const; + virtual void DeliverSignal(int signal) {} // Original code: public: diff --git a/lldb/tools/lldb-mi/MICmnStreamStdin.cpp b/lldb/tools/lldb-mi/MICmnStreamStdin.cpp index c57ca4408ab..76f3593732b 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStdin.cpp +++ b/lldb/tools/lldb-mi/MICmnStreamStdin.cpp @@ -33,6 +33,7 @@ #else #include "MICmnStreamStdinLinux.h" #endif // defined( _MSC_VER ) +#include <string.h> // For std::strerror() //++ ------------------------------------------------------------------------------------ // Details: CMICmnStreamStdin constructor. @@ -49,6 +50,7 @@ CMICmnStreamStdin::CMICmnStreamStdin(void) , m_bShowPrompt(true) , m_bRedrawPrompt(true) , m_pStdinReadHandler(nullptr) + , m_pCmdBuffer(nullptr) { } @@ -103,6 +105,9 @@ CMICmnStreamStdin::Initialize(void) return MIstatus::failure; } + if (bOk) + m_pCmdBuffer = new MIchar[m_constBufferSize]; + // Other resources required if (bOk) { @@ -142,6 +147,12 @@ CMICmnStreamStdin::Shutdown(void) ClrErrorDescription(); + if (m_pCmdBuffer != nullptr) + { + delete[] m_pCmdBuffer; + m_pCmdBuffer = nullptr; + } + bool bOk = MIstatus::success; CMIUtilString errMsg; @@ -355,7 +366,28 @@ CMICmnStreamStdin::MonitorStdin(bool &vrwbYesAlive) const MIchar * CMICmnStreamStdin::ReadLine(CMIUtilString &vwErrMsg) { - return m_pStdinReadHandler->ReadLine(vwErrMsg); + vwErrMsg.clear(); + + // Read user input + const MIchar *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); + if (pText == nullptr) + { + if (::ferror(stdin) != 0) + vwErrMsg = ::strerror(errno); + return nullptr; + } + + // Strip off new line characters + for (MIchar *pI = m_pCmdBuffer; *pI != '\0'; pI++) + { + if ((*pI == '\n') || (*pI == '\r')) + { + *pI = '\0'; + break; + } + } + + return pText; } //++ ------------------------------------------------------------------------------------ diff --git a/lldb/tools/lldb-mi/MICmnStreamStdin.h b/lldb/tools/lldb-mi/MICmnStreamStdin.h index a6779d53166..ce81ddfb748 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStdin.h +++ b/lldb/tools/lldb-mi/MICmnStreamStdin.h @@ -84,6 +84,7 @@ class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase, bool SetVisitor(IStreamStdin &vrVisitor); bool SetOSStdinHandler(IOSStdinHandler &vrHandler); void OnExitHandler(void); + const MIchar *ReadLine(CMIUtilString &vwErrMsg); // Overridden: public: @@ -104,7 +105,6 @@ class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase, void operator=(const CMICmnStreamStdin &); bool MonitorStdin(bool &vrwbYesExit); - const MIchar *ReadLine(CMIUtilString &vwErrMsg); bool InputAvailable(bool &vbAvail); // Bytes are available on stdin @@ -122,4 +122,6 @@ class CMICmnStreamStdin : public CMICmnBase, public CMIUtilThreadActiveObjBase, bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), false = no prompt bool m_bRedrawPrompt; // True = Prompt needs to be redrawn IOSStdinHandler *m_pStdinReadHandler; + static const int m_constBufferSize = 2048; + MIchar *m_pCmdBuffer; }; diff --git a/lldb/tools/lldb-mi/MIDriver.cpp b/lldb/tools/lldb-mi/MIDriver.cpp index 8cd115301ad..954815817c2 100644 --- a/lldb/tools/lldb-mi/MIDriver.cpp +++ b/lldb/tools/lldb-mi/MIDriver.cpp @@ -500,42 +500,6 @@ CMIDriver::GetDriverIsGDBMICompatibleDriver(void) const } //++ ------------------------------------------------------------------------------------ -// Details: Callback function for monitoring stream stdin object. Part of the visitor -// pattern. -// This function is called by the CMICmnStreamStdin::CThreadStdin -// "stdin monitor" thread (ID). -// Type: Overridden. -// Args: vStdInBuffer - (R) Copy of the current stdin line data. -// vrbYesExit - (RW) True = yes exit stdin monitoring, false = continue monitor. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMIDriver::ReadLine(const CMIUtilString &vStdInBuffer, bool &vrwbYesExit) -{ - // For debugging. Update prompt show stdin is working - // printf( "%s\n", vStdInBuffer.c_str() ); - // fflush( stdout ); - - // Special case look for the quit command here so stop monitoring stdin stream - // So we do not go back to fgetc() and wait and hang thread on exit - if (vStdInBuffer == "quit") - vrwbYesExit = true; - - // 1. Put new line in the queue container by stdin monitor thread - // 2. Then *this driver calls ReadStdinLineQueue() when ready to read the queue in its - // own thread - const bool bOk = QueueMICommand(vStdInBuffer); - - // Check to see if the *this driver is shutting down (exit application) - if (!vrwbYesExit) - vrwbYesExit = m_bDriverIsExiting; - - return bOk; -} - -//++ ------------------------------------------------------------------------------------ // Details: Start worker threads for the driver. // Type: Method. // Args: None. @@ -551,16 +515,6 @@ CMIDriver::StartWorkerThreads(void) // Grab the thread manager CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); - // Start the stdin thread - bOk &= m_rStdin.SetVisitor(*this); - if (bOk && !rThreadMgr.ThreadStart<CMICmnStreamStdin>(m_rStdin)) - { - const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), - CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); - SetErrorDescriptionn(errMsg); - return MIstatus::failure; - } - // Start the event polling thread if (bOk && !rThreadMgr.ThreadStart<CMICmnLLDBDebugger>(m_rLldbDebugger)) { @@ -627,11 +581,31 @@ CMIDriver::DoMainLoop(void) // While the app is active while (!m_bExitApp) { - // Poll stdin queue and dispatch - if (!ReadStdinLineQueue()) + CMIUtilString errorText; + const MIchar *pCmd = m_rStdin.ReadLine (errorText); + if (pCmd != nullptr) { - // Something went wrong - break; + CMIUtilString lineText(pCmd); + if (!lineText.empty ()) + { + if (lineText == "quit") + { + // We want to be exiting when receiving a quit command + m_bExitApp = true; + break; + } + + bool bOk = false; + { + // Lock Mutex before processing commands so that we don't disturb an event + // being processed + CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); + bOk = InterpretCommand(lineText); + } + // Draw prompt if desired + if (bOk && m_rStdin.GetEnablePrompt()) + m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt()); + } } } @@ -648,72 +622,6 @@ CMIDriver::DoMainLoop(void) } //++ ------------------------------------------------------------------------------------ -// Details: *this driver sits and waits for input to the stdin line queue shared by *this -// driver and the stdin monitor thread, it queues, *this reads, interprets and -// reacts. -// This function is used by the application's main thread. -// Type: Method. -// Args: None. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMIDriver::ReadStdinLineQueue(void) -{ - // True when queue contains input - bool bHaveInput = false; - - // Stores the current input line - CMIUtilString lineText; - { - // Lock while we access the queue - CMIUtilThreadLock lock(m_threadMutex); - if (!m_queueStdinLine.empty()) - { - lineText = m_queueStdinLine.front(); - m_queueStdinLine.pop(); - bHaveInput = !lineText.empty(); - } - } - - // Process while we have input - if (bHaveInput) - { - if (lineText == "quit") - { - // We want to be exiting when receiving a quit command - m_bExitApp = true; - return MIstatus::success; - } - - // Process the command - bool bOk = false; - { - // Lock Mutex before processing commands so that we don't disturb an event - // that is being processed. - CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); - bOk = InterpretCommand(lineText); - } - - // Draw prompt if desired - if (bOk && m_rStdin.GetEnablePrompt()) - m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt()); - - // Input has been processed - bHaveInput = false; - } - else - { - // Give resources back to the OS - const std::chrono::milliseconds time(1); - std::this_thread::sleep_for(time); - } - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ // Details: Set things in motion, set state etc that brings *this driver (and the // application) to a tidy shutdown. // This function is used by the application's main thread. @@ -926,42 +834,6 @@ CMIDriver::GetId(void) const } //++ ------------------------------------------------------------------------------------ -// Details: Inject a command into the command processing system to be interpreted as a -// command read from stdin. The text representing the command is also written -// out to stdout as the command did not come from via stdin. -// Type: Method. -// Args: vMICmd - (R) Text data representing a possible command. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMIDriver::InjectMICommand(const CMIUtilString &vMICmd) -{ - const bool bOk = m_rStdOut.WriteMIResponse(vMICmd); - - return bOk && QueueMICommand(vMICmd); -} - -//++ ------------------------------------------------------------------------------------ -// Details: Add a new command candidate to the command queue to be processed by the -// command system. -// Type: Method. -// Args: vMICmd - (R) Text data representing a possible command. -// Return: MIstatus::success - Functional succeeded. -// MIstatus::failure - Functional failed. -// Throws: None. -//-- -bool -CMIDriver::QueueMICommand(const CMIUtilString &vMICmd) -{ - CMIUtilThreadLock lock(m_threadMutex); - m_queueStdinLine.push(vMICmd); - - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ // Details: Interpret the text data and match against current commands to see if there // is a match. If a match then the command is issued and actioned on. The // text data if not understood by *this driver is past on to the Fall Thru @@ -1093,7 +965,7 @@ CMIDriver::SetExitApplicationFlag(const bool vbForceExit) // but halt the inferior program being debugged instead if (m_eCurrentDriverState == eDriverState_RunningDebugging) { - InjectMICommand("-exec-interrupt"); + InterpretCommand("-exec-interrupt"); return; } @@ -1302,9 +1174,9 @@ CMIDriver::GetExecutableFileNamePathOnCmdLine(void) const bool CMIDriver::LocalDebugSessionStartupInjectCommands(void) { - const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols %s", m_strCmdLineArgExecuteableFileNamePath.c_str())); - - return InjectMICommand(strCmd); + const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols \"%s\"", m_strCmdLineArgExecuteableFileNamePath.c_str())); + const bool bOk = CMICmnStreamStdout::TextToStdout(strCmd); + return (bOk && InterpretCommand(strCmd)); } //++ ------------------------------------------------------------------------------------ @@ -1335,3 +1207,18 @@ CMIDriver::IsDriverDebuggingArgExecutable(void) const { return m_bDriverDebuggingArgExecutable; } + +//++ ------------------------------------------------------------------------------------ +// Details: Gets called when lldb-mi gets a signal. Stops the process if it was SIGINT. +// +// Type: Method. +// Args: signal that was delivered +// Return: None. +// Throws: None. +//-- +void +CMIDriver::DeliverSignal(int signal) +{ + if (signal == SIGINT && (m_eCurrentDriverState == eDriverState_RunningDebugging)) + InterpretCommand("-exec-interrupt"); +} diff --git a/lldb/tools/lldb-mi/MIDriver.h b/lldb/tools/lldb-mi/MIDriver.h index dafe1bedcf0..d6ccddf8b72 100644 --- a/lldb/tools/lldb-mi/MIDriver.h +++ b/lldb/tools/lldb-mi/MIDriver.h @@ -51,7 +51,6 @@ class CMICmnStreamStdout; class CMIDriver : public CMICmnBase, public CMIDriverMgr::IDriver, public CMIDriverBase, - public CMICmnStreamStdin::IStreamStdin, public MI::ISingleton<CMIDriver> { friend class MI::ISingleton<CMIDriver>; @@ -101,7 +100,6 @@ class CMIDriver : public CMICmnBase, bool WriteMessageToLog(const CMIUtilString &vMessage); bool SetEnableFallThru(const bool vbYes); bool GetEnableFallThru(void) const; - bool InjectMICommand(const CMIUtilString &vMICmd); bool HaveExecutableFileNamePathOnCmdLine(void) const; const CMIUtilString &GetExecutableFileNamePathOnCmdLine(void) const; @@ -128,8 +126,7 @@ class CMIDriver : public CMICmnBase, virtual FILE *GetStderr(void) const; virtual const CMIUtilString &GetDriverName(void) const; virtual const CMIUtilString &GetDriverId(void) const; - // From CMICmnStreamStdin - virtual bool ReadLine(const CMIUtilString &vStdInBuffer, bool &vrbYesExit); + virtual void DeliverSignal(int signal); // Typedefs: private: @@ -142,7 +139,6 @@ class CMIDriver : public CMICmnBase, void operator=(const CMIDriver &); lldb::SBError ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting); - bool ReadStdinLineQueue(void); bool DoAppQuit(void); bool InterpretCommand(const CMIUtilString &vTextLine); bool InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid); @@ -152,7 +148,6 @@ class CMIDriver : public CMICmnBase, bool StopWorkerThreads(void); bool InitClientIDEToMIDriver(void) const; bool InitClientIDEEclipse(void) const; - bool QueueMICommand(const CMIUtilString &vMICmd); bool LocalDebugSessionStartupInjectCommands(void); // Overridden: @@ -168,7 +163,6 @@ class CMIDriver : public CMICmnBase, // bool m_bFallThruToOtherDriverEnabled; // True = yes fall through, false = do not pass on command CMIUtilThreadMutex m_threadMutex; - QueueStdinLine_t m_queueStdinLine; // Producer = stdin monitor, consumer = *this driver bool m_bDriverIsExiting; // True = yes, driver told to quit, false = continue working void *m_handleMainThread; // *this driver is run by the main thread CMICmnStreamStdin &m_rStdin; diff --git a/lldb/tools/lldb-mi/MIDriverMain.cpp b/lldb/tools/lldb-mi/MIDriverMain.cpp index 5557799d368..dd1e1d18646 100644 --- a/lldb/tools/lldb-mi/MIDriverMain.cpp +++ b/lldb/tools/lldb-mi/MIDriverMain.cpp @@ -132,9 +132,8 @@ sigint_handler(int vSigno) CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGINT", vSigno)); - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - // Signal MI to shutdown or halt a running debug session - CMICmnStreamStdin::Instance().SetCtrlCHit(); + // Send signal to driver so that it can take suitable action + rDriverMgr.DeliverSignal (vSigno); } // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent @@ -165,8 +164,8 @@ sigtstp_handler(int vSigno) CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGTSTP", vSigno)); - // Signal MI to shutdown - CMICmnStreamStdin::Instance().SetCtrlCHit(); + // Send signal to driver so that it can take suitable action + rDriverMgr.DeliverSignal (vSigno); } // ToDo: Reevaluate if this function needs to be implemented like the UNIX equivalent @@ -196,8 +195,8 @@ sigcont_handler(int vSigno) CMICmnLog::Instance().WriteLog(CMIUtilString::Format(MIRSRC(IDS_PROCESS_SIGNAL_RECEIVED), "SIGCONT", vSigno)); - // Signal MI to shutdown - CMICmnStreamStdin::Instance().SetCtrlCHit(); + // Send signal to driver so that it can take suitable action + rDriverMgr.DeliverSignal (vSigno); } //++ ------------------------------------------------------------------------------------ diff --git a/lldb/tools/lldb-mi/MIDriverMgr.cpp b/lldb/tools/lldb-mi/MIDriverMgr.cpp index ca900ca6e88..9ef7a4dec27 100644 --- a/lldb/tools/lldb-mi/MIDriverMgr.cpp +++ b/lldb/tools/lldb-mi/MIDriverMgr.cpp @@ -778,3 +778,19 @@ CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const return pDriver; } + + +//++ ------------------------------------------------------------------------------------ +// Details: Gets called when lldb-mi gets a signal. Passed signal to current driver. +// +// Type: Method. +// Args: signal that was delivered +// Return: None. +// Throws: None. +//-- +void +CMIDriverMgr::DeliverSignal(int signal) +{ + if (m_pDriverCurrent != nullptr) + m_pDriverCurrent->DeliverSignal(signal); +} diff --git a/lldb/tools/lldb-mi/MIDriverMgr.h b/lldb/tools/lldb-mi/MIDriverMgr.h index 9e1e121405c..30bc9715581 100644 --- a/lldb/tools/lldb-mi/MIDriverMgr.h +++ b/lldb/tools/lldb-mi/MIDriverMgr.h @@ -79,6 +79,7 @@ class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr> virtual bool GetDriverIsGDBMICompatibleDriver(void) const = 0; virtual bool SetId(const CMIUtilString &vId) = 0; virtual const CMIUtilString &GetId(void) const = 0; + virtual void DeliverSignal(int signal) = 0; // Not part of the interface, ignore /* dtor */ virtual ~IDriver(void) {} @@ -106,6 +107,7 @@ class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr> CMIUtilString DriverGetError(void) const; CMIUtilString DriverGetName(void) const; lldb::SBDebugger *DriverGetTheDebugger(void); + void DeliverSignal(int signal); // Typedef: private: |

