[Lldb-commits] [lldb] r160100 - in /lldb/trunk: include/lldb/Core/ConnectionFileDescriptor.h source/Core/ConnectionFileDescriptor.cpp

Jim Ingham jingham at apple.com
Wed Jul 11 18:17:55 PDT 2012


Author: jingham
Date: Wed Jul 11 20:17:55 2012
New Revision: 160100

URL: http://llvm.org/viewvc/llvm-project?rev=160100&view=rev
Log:
Add a command channel to wait on along with the file descriptor the ConnectionFileDescriptor class is managing, so we can always pop ourselves out of our select call regardless of how well behaved the channel we are talking to is.

<rdar://problem/11448282>

Modified:
    lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
    lldb/trunk/source/Core/ConnectionFileDescriptor.cpp

Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h?rev=160100&r1=160099&r2=160100&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original)
+++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Wed Jul 11 20:17:55 2012
@@ -20,6 +20,7 @@
 // Project includes
 #include "lldb/Core/Connection.h"
 #include "lldb/Host/Mutex.h"
+#include "lldb/Host/Predicate.h"
 #include "lldb/Host/SocketAddress.h"
 
 namespace lldb_private {
@@ -70,6 +71,12 @@
 
 protected:
     
+    void
+    InitializeCommandFileDescriptor ();
+    
+    void
+    CloseCommandFileDescriptor ();
+
     lldb::ConnectionStatus
     BytesAvailable (uint32_t timeout_usec, Error *error_ptr);
     
@@ -105,6 +112,8 @@
     SocketAddress m_udp_send_sockaddr;
     bool m_should_close_fd; // True if this class should close the file descriptor when it goes away.
     uint32_t m_socket_timeout_usec;
+    int m_command_fd_send;        // A pipe that we select on the reading end of along with
+    int m_command_fd_receive;     // m_fd_recv so we can force ourselves out of the select.
     Mutex m_mutex;
     
     static in_port_t

Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=160100&r1=160099&r2=160100&view=diff
==============================================================================
--- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original)
+++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Wed Jul 11 20:17:55 2012
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 // C++ Includes
 // Other libraries and framework includes
@@ -74,6 +75,8 @@
     m_udp_send_sockaddr (),
     m_should_close_fd (false), 
     m_socket_timeout_usec(0),
+    m_command_fd_send(-1),
+    m_command_fd_receive(-1),
     m_mutex (Mutex::eMutexTypeRecursive)
 {
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
@@ -90,6 +93,8 @@
     m_udp_send_sockaddr (),
     m_should_close_fd (owns_fd),
     m_socket_timeout_usec(0),
+    m_command_fd_send(-1),
+    m_command_fd_receive(-1),
     m_mutex (Mutex::eMutexTypeRecursive)
 {
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
@@ -104,6 +109,46 @@
     if (log)
         log->Printf ("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", this);
     Disconnect (NULL);
+    CloseCommandFileDescriptor ();
+}
+
+void
+ConnectionFileDescriptor::InitializeCommandFileDescriptor ()
+{
+    CloseCommandFileDescriptor();
+    
+    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
+    // Make the command file descriptor here:
+    int filedes[2];
+    int result = pipe (filedes);
+    if (result != 0)
+    {
+        if (log)
+            log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor () - could not make pipe: %s",
+                         this,
+                         strerror(errno));
+    }
+    else
+    {
+        m_command_fd_receive = filedes[0];
+        m_command_fd_send    = filedes[1];
+    }
+}
+
+void
+ConnectionFileDescriptor::CloseCommandFileDescriptor ()
+{
+    if (m_command_fd_receive != -1)
+    {
+        close (m_command_fd_receive);
+        m_command_fd_receive = -1;
+    }
+    
+    if (m_command_fd_send != -1)
+    {
+        close (m_command_fd_send);
+        m_command_fd_send = -1;
+    }
 }
 
 bool
@@ -120,6 +165,8 @@
     if (log)
         log->Printf ("%p ConnectionFileDescriptor::Connect (url = '%s')", this, s);
 
+    InitializeCommandFileDescriptor();
+    
     if (s && s[0])
     {
         char *end = NULL;
@@ -157,7 +204,7 @@
             if (success)
             {
                 // We have what looks to be a valid file descriptor, but we 
-                // should make it is. We currently are doing this by trying to
+                // should make sure it is. We currently are doing this by trying to
                 // get the flags from the file descriptor and making sure it 
                 // isn't a bad fd.
                 errno = 0;
@@ -239,32 +286,44 @@
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
     if (log)
         log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", this);
-    if (m_should_close_fd == false)
-    {
-        m_fd_send = m_fd_recv = -1;
-        return eConnectionStatusSuccess;
-    }
+
     ConnectionStatus status = eConnectionStatusSuccess;
+
     if (m_fd_send >= 0 || m_fd_recv >= 0)
     {
-        if (m_fd_send == m_fd_recv)
+        if (m_should_close_fd == false)
         {
-            // Both file descriptors are the same, only close one
-            m_fd_recv = -1;
-            status = Close (m_fd_send, error_ptr);
+            m_fd_send = m_fd_recv = -1;
         }
         else
         {
-            // File descriptors are the different, close both if needed
-            if (m_fd_send >= 0)
+            if (m_fd_send == m_fd_recv)
+            {
+                // Both file descriptors are the same, only close one
+                m_fd_recv = -1;
                 status = Close (m_fd_send, error_ptr);
-            if (m_fd_recv >= 0)
+            }
+            else
             {
-                ConnectionStatus recv_status = Close (m_fd_recv, error_ptr);
-                if (status == eConnectionStatusSuccess)
-                    status = recv_status;
+                // File descriptors are the different, close both if needed
+                if (m_fd_send >= 0)
+                    status = Close (m_fd_send, error_ptr);
+                if (m_fd_recv >= 0)
+                {
+                    ConnectionStatus recv_status = Close (m_fd_recv, error_ptr);
+                    if (status == eConnectionStatusSuccess)
+                        status = recv_status;
+                }
             }
         }
+        
+        // Now write a byte to the command pipe to wake our Reader if it is stuck in read.
+        if (m_command_fd_send != -1 )
+        {
+            write (m_command_fd_send, "q", 1);
+            close (m_command_fd_send);
+            m_command_fd_send = -1;
+        }
     }
     return status;
 }
@@ -283,42 +342,13 @@
 
     ssize_t bytes_read = 0;
 
-    switch (m_fd_recv_type)
+    status = BytesAvailable (timeout_usec, error_ptr);
+    if (status == eConnectionStatusSuccess)
     {
-    case eFDTypeFile:       // Other FD requireing read/write
-        status = BytesAvailable (timeout_usec, error_ptr);
-        if (status == eConnectionStatusSuccess)
+        do
         {
-            do
-            {
-                bytes_read = ::read (m_fd_recv, dst, dst_len);
-            } while (bytes_read < 0 && errno == EINTR);
-        }
-        break;
-
-    case eFDTypeSocket:     // Socket requiring send/recv
-        if (SetSocketReceiveTimeout (timeout_usec))
-        {
-            status = eConnectionStatusSuccess;
-            do
-            {
-                bytes_read = ::recv (m_fd_recv, dst, dst_len, 0);
-            } while (bytes_read < 0 && errno == EINTR);
-        }
-        break;
-
-    case eFDTypeSocketUDP:  // Unconnected UDP socket requiring sendto/recvfrom
-        if (SetSocketReceiveTimeout (timeout_usec))
-        {
-            status = eConnectionStatusSuccess;
-            SocketAddress from (m_udp_send_sockaddr);
-            socklen_t from_len = m_udp_send_sockaddr.GetLength();
-            do
-            {
-                bytes_read = ::recvfrom (m_fd_recv, dst, dst_len, 0, (struct sockaddr *)&from, &from_len);
-            } while (bytes_read < 0 && errno == EINTR);
-        }
-        break;
+            bytes_read = ::read (m_fd_recv, dst, dst_len);
+        } while (bytes_read < 0 && errno == EINTR);
     }
 
     if (status != eConnectionStatusSuccess)
@@ -546,7 +576,9 @@
         fd_set read_fds;
         FD_ZERO (&read_fds);
         FD_SET (m_fd_recv, &read_fds);
-        int nfds = m_fd_recv + 1;
+        if (m_command_fd_receive != -1)
+            FD_SET (m_command_fd_receive, &read_fds);
+        int nfds = (m_fd_recv > m_command_fd_receive ? m_fd_recv : m_command_fd_receive) + 1;
         
         Error error;
 
@@ -594,7 +626,26 @@
         }
         else if (num_set_fds > 0)
         {
-            return eConnectionStatusSuccess;
+            if (m_command_fd_receive != -1 && FD_ISSET(m_command_fd_receive, &read_fds))
+            {
+                // We got a command to exit.  Read the data from that pipe:
+                char buffer[16];
+                ssize_t bytes_read;
+                
+                do
+                {
+                    bytes_read = ::read (m_command_fd_receive, buffer, sizeof(buffer));
+                } while (bytes_read < 0 && errno == EINTR);
+                assert (bytes_read == 1 && buffer[0] == 'q');
+                
+                if (log)
+                    log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
+                                this, (int) bytes_read, buffer);
+                
+                return eConnectionStatusEndOfFile;
+            }
+            else
+                return eConnectionStatusSuccess;
         }
     }
 





More information about the lldb-commits mailing list