[Lldb-commits] [lldb] r254200 - [LLGS] Don't forward I/O when process is stopped

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Fri Nov 27 05:33:29 PST 2015


Author: labath
Date: Fri Nov 27 07:33:29 2015
New Revision: 254200

URL: http://llvm.org/viewvc/llvm-project?rev=254200&view=rev
Log:
[LLGS] Don't forward I/O when process is stopped

Summary:
This makes sure we do not attempt to send output over the gdb-remote protocol when the client is
not expecting it (i.e., after sending the stop-reply packet). Normally, this should not happen
(the process cannot generate output when it is stopped), but due to the fact that pty
communication is asynchronous in the linux kernel (llvm.org/pr25652), we may sometimes get this
output too late. Instead, we just hold the output, and send it next time we resume. This is not
ideal, but at least it makes sure we do not violate the remote protocol. Given that this happens
extremely rarely it's not worth trying to work around it with sleeps or something like that.

I also remove the m_stdio_communication_mutex, as all of LLGS is now single-threaded anyway.

Reviewers: tberghammer, ovyalov

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D15019

Modified:
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp?rev=254200&r1=254199&r2=254200&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Fri Nov 27 07:33:29 2015
@@ -44,6 +44,7 @@
 #include "lldb/Host/common/NativeProcessProtocol.h"
 #include "lldb/Host/common/NativeThreadProtocol.h"
 #include "lldb/Utility/JSON.h"
+#include "lldb/Utility/LLDBAssert.h"
 
 // Project includes
 #include "Utility/StringExtractorGDBRemote.h"
@@ -860,21 +861,30 @@ GDBRemoteCommunicationServerLLGS::Proces
                 StateAsCString (state));
     }
 
-    // Make sure we get all of the pending stdout/stderr from the inferior
-    // and send it to the lldb host before we send the state change
-    // notification
-    SendProcessOutput();
-
     switch (state)
     {
-    case StateType::eStateExited:
-        HandleInferiorState_Exited (process);
+    case StateType::eStateRunning:
+        StartSTDIOForwarding();
         break;
 
     case StateType::eStateStopped:
+        // Make sure we get all of the pending stdout/stderr from the inferior
+        // and send it to the lldb host before we send the state change
+        // notification
+        SendProcessOutput();
+        // Then stop the forwarding, so that any late output (see llvm.org/pr25652) does not
+        // interfere with our protocol.
+        StopSTDIOForwarding();
         HandleInferiorState_Stopped (process);
         break;
 
+    case StateType::eStateExited:
+        // Same as above
+        SendProcessOutput();
+        StopSTDIOForwarding();
+        HandleInferiorState_Exited (process);
+        break;
+
     default:
         if (log)
         {
@@ -975,7 +985,6 @@ GDBRemoteCommunicationServerLLGS::SetSTD
         return error;
     }
 
-    Mutex::Locker locker(m_stdio_communication_mutex);
     m_stdio_communication.SetCloseOnEOF (false);
     m_stdio_communication.SetConnection (conn_up.release());
     if (!m_stdio_communication.IsConnected ())
@@ -984,33 +993,42 @@ GDBRemoteCommunicationServerLLGS::SetSTD
         return error;
     }
 
+    return Error();
+}
+
+void
+GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding()
+{
+    // Don't forward if not connected (e.g. when attaching).
+    if (! m_stdio_communication.IsConnected())
+        return;
+
     // llgs local-process debugging may specify PTY paths, which will make these
     // file actions non-null
     // process launch -e/o will also make these file actions non-null
     // nullptr means that the traffic is expected to flow over gdb-remote protocol
-    if (
-        m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
-        m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr
-        )
-    {
-        // output from the process must be forwarded over gdb-remote
-        m_stdio_handle_up = m_mainloop.RegisterReadObject(
-                m_stdio_communication.GetConnection()->GetReadObject(),
-                [this] (MainLoopBase &) { SendProcessOutput(); }, error);
-        if (! m_stdio_handle_up)
-        {
-            m_stdio_communication.Disconnect();
-            return error;
-        }
-    }
+    if ( m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) &&
+         m_process_launch_info.GetFileActionForFD(STDERR_FILENO))
+        return;
 
-    return Error();
+    Error error;
+    lldbassert(! m_stdio_handle_up);
+    m_stdio_handle_up = m_mainloop.RegisterReadObject(
+            m_stdio_communication.GetConnection()->GetReadObject(),
+            [this] (MainLoopBase &) { SendProcessOutput(); }, error);
+
+    if (! m_stdio_handle_up)
+    {
+        // Not much we can do about the failure. Log it and continue without forwarding.
+        if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+            log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio forwarding: %s",
+                        __FUNCTION__, error.AsCString());
+    }
 }
 
 void
 GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding()
 {
-    Mutex::Locker locker(m_stdio_communication_mutex);
     m_stdio_handle_up.reset();
 }
 
@@ -1020,7 +1038,6 @@ GDBRemoteCommunicationServerLLGS::SendPr
     char buffer[1024];
     ConnectionStatus status;
     Error error;
-    Mutex::Locker locker(m_stdio_communication_mutex);
     while (true)
     {
         size_t bytes_read = m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error);
@@ -1931,7 +1948,6 @@ GDBRemoteCommunicationServerLLGS::Handle
         // TODO: enqueue this block in circular buffer and send window size to remote host
         ConnectionStatus status;
         Error error;
-        Mutex::Locker locker(m_stdio_communication_mutex);
         m_stdio_communication.Write(tmp, read, status, &error);
         if (error.Fail())
         {
@@ -2835,7 +2851,6 @@ GDBRemoteCommunicationServerLLGS::MaybeC
 {
     Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
 
-    Mutex::Locker locker(m_stdio_communication_mutex);
     // Tell the stdio connection to shut down.
     if (m_stdio_communication.IsConnected())
     {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h?rev=254200&r1=254199&r2=254200&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h Fri Nov 27 07:33:29 2015
@@ -122,7 +122,6 @@ protected:
     Mutex m_debugged_process_mutex;
     NativeProcessProtocolSP m_debugged_process_sp;
 
-    Mutex m_stdio_communication_mutex; // Protects m_stdio_communication and m_stdio_handle_up
     Communication m_stdio_communication;
     MainLoop::ReadHandleUP m_stdio_handle_up;
 
@@ -298,6 +297,9 @@ private:
     SendProcessOutput ();
 
     void
+    StartSTDIOForwarding();
+
+    void
     StopSTDIOForwarding();
 
     //------------------------------------------------------------------




More information about the lldb-commits mailing list