[Lldb-commits] [lldb] r230003 - Reduce number of threads in lldb-mi.

Hafiz Abid Qadeer hafiz_abid at mentor.com
Fri Feb 20 02:20:07 PST 2015


Author: abidh
Date: Fri Feb 20 04:20:05 2015
New Revision: 230003

URL: http://llvm.org/viewvc/llvm-project?rev=230003&view=rev
Log:
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.


Modified:
    lldb/trunk/tools/lldb-mi/Driver.h
    lldb/trunk/tools/lldb-mi/MICmnStreamStdin.cpp
    lldb/trunk/tools/lldb-mi/MICmnStreamStdin.h
    lldb/trunk/tools/lldb-mi/MIDriver.cpp
    lldb/trunk/tools/lldb-mi/MIDriver.h
    lldb/trunk/tools/lldb-mi/MIDriverMain.cpp
    lldb/trunk/tools/lldb-mi/MIDriverMgr.cpp
    lldb/trunk/tools/lldb-mi/MIDriverMgr.h

Modified: lldb/trunk/tools/lldb-mi/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/Driver.h?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/Driver.h (original)
+++ lldb/trunk/tools/lldb-mi/Driver.h Fri Feb 20 04:20:05 2015
@@ -64,6 +64,7 @@ class Driver : public lldb::SBBroadcaste
     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:

Modified: lldb/trunk/tools/lldb-mi/MICmnStreamStdin.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnStreamStdin.cpp?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnStreamStdin.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmnStreamStdin.cpp Fri Feb 20 04:20:05 2015
@@ -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(voi
     , 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 &vr
 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;
 }
 
 //++ ------------------------------------------------------------------------------------

Modified: lldb/trunk/tools/lldb-mi/MICmnStreamStdin.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnStreamStdin.h?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnStreamStdin.h (original)
+++ lldb/trunk/tools/lldb-mi/MICmnStreamStdin.h Fri Feb 20 04:20:05 2015
@@ -84,6 +84,7 @@ class CMICmnStreamStdin : public CMICmnB
     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 CMICmnB
     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 CMICmnB
     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;
 };

Modified: lldb/trunk/tools/lldb-mi/MIDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIDriver.cpp?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIDriver.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MIDriver.cpp Fri Feb 20 04:20:05 2015
@@ -500,42 +500,6 @@ CMIDriver::GetDriverIsGDBMICompatibleDri
 }
 
 //++ ------------------------------------------------------------------------------------
-// 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
     // 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::GetExecutableFileNamePathOnCm
 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::IsDriverDebuggingArgExecutabl
 {
     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");
+}

Modified: lldb/trunk/tools/lldb-mi/MIDriver.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIDriver.h?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIDriver.h (original)
+++ lldb/trunk/tools/lldb-mi/MIDriver.h Fri Feb 20 04:20:05 2015
@@ -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;

Modified: lldb/trunk/tools/lldb-mi/MIDriverMain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIDriverMain.cpp?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIDriverMain.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MIDriverMain.cpp Fri Feb 20 04:20:05 2015
@@ -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);
 }
 
 //++ ------------------------------------------------------------------------------------

Modified: lldb/trunk/tools/lldb-mi/MIDriverMgr.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIDriverMgr.cpp?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIDriverMgr.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MIDriverMgr.cpp Fri Feb 20 04:20:05 2015
@@ -778,3 +778,19 @@ CMIDriverMgr::GetDriver(const CMIUtilStr
 
     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);
+}

Modified: lldb/trunk/tools/lldb-mi/MIDriverMgr.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIDriverMgr.h?rev=230003&r1=230002&r2=230003&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIDriverMgr.h (original)
+++ lldb/trunk/tools/lldb-mi/MIDriverMgr.h Fri Feb 20 04:20:05 2015
@@ -79,6 +79,7 @@ class CMIDriverMgr : public CMICmnBase,
         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,
     CMIUtilString DriverGetError(void) const;
     CMIUtilString DriverGetName(void) const;
     lldb::SBDebugger *DriverGetTheDebugger(void);
+    void DeliverSignal(int signal);
 
     // Typedef:
   private:





More information about the lldb-commits mailing list