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

Jim Ingham jingham at apple.com
Mon Jul 16 18:47:11 PDT 2012


Author: jingham
Date: Mon Jul 16 20:47:11 2012
New Revision: 160336

URL: http://llvm.org/viewvc/llvm-project?rev=160336&view=rev
Log:
Lock around reading as well as connecting & disconnecting so we don't start reading after
someone has set our file descriptor to -1 and crash in FD_SET...
<rdar://problem/11653966>

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=160336&r1=160335&r2=160336&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original)
+++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Mon Jul 16 20:47:11 2012
@@ -112,9 +112,11 @@
     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;
+    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;          
+    bool m_shutting_down;        // This marks that we are shutting down so if we get woken up from BytesAvailable
+                                 // to disconnect, we won't try to read again.
     
     static in_port_t
     GetSocketPort (int fd);

Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=160336&r1=160335&r2=160336&view=diff
==============================================================================
--- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original)
+++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Mon Jul 16 20:47:11 2012
@@ -77,7 +77,8 @@
     m_socket_timeout_usec(0),
     m_command_fd_send(-1),
     m_command_fd_receive(-1),
-    m_mutex (Mutex::eMutexTypeRecursive)
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_shutting_down (false)
 {
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
     if (log)
@@ -95,7 +96,8 @@
     m_socket_timeout_usec(0),
     m_command_fd_send(-1),
     m_command_fd_receive(-1),
-    m_mutex (Mutex::eMutexTypeRecursive)
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_shutting_down (false)
 {
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
     if (log)
@@ -282,50 +284,72 @@
 ConnectionStatus
 ConnectionFileDescriptor::Disconnect (Error *error_ptr)
 {
-    Mutex::Locker locker (m_mutex);
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
     if (log)
         log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", this);
 
     ConnectionStatus status = eConnectionStatusSuccess;
 
-    if (m_fd_send >= 0 || m_fd_recv >= 0)
+    if (m_fd_send < 0 && m_fd_recv < 0)
     {
-        if (m_should_close_fd == false)
+        if (log)
+            log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", this);
+        return eConnectionStatusSuccess;
+    }
+    
+    // Try to get the ConnectionFileDescriptor's mutex.  If we fail, that is quite likely
+    // because somebody is doing a blocking read on our file descriptor.  If that's the case,
+    // then send the "q" char to the command file channel so the read will wake up and the connection
+    // will then know to shut down.
+    
+    m_shutting_down = true;
+    
+    Mutex::Locker locker;
+    bool got_lock= locker.TryLock (m_mutex);
+    
+    if (!got_lock)
+    {
+        if (m_command_fd_send != -1 )
         {
-            m_fd_send = m_fd_recv = -1;
+            write (m_command_fd_send, "q", 1);
+            close (m_command_fd_send);
+            m_command_fd_send = -1;
+        }
+        locker.Lock (m_mutex);
+    }
+    
+    if (m_should_close_fd == true)
+    {
+        if (m_fd_send == m_fd_recv)
+        {
+            status = Close (m_fd_send, error_ptr);
         }
         else
         {
-            if (m_fd_send == m_fd_recv)
-            {
-                // Both file descriptors are the same, only close one
-                m_fd_recv = -1;
+            // File descriptors are the different, close both if needed
+            if (m_fd_send >= 0)
                 status = Close (m_fd_send, error_ptr);
-            }
-            else
+            if (m_fd_recv >= 0)
             {
-                // 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;
-                }
+                ConnectionStatus recv_status = Close (m_fd_recv, error_ptr);
+                if (status == eConnectionStatusSuccess)
+                    status = recv_status;
             }
         }
+    }
+
+    // Now set all our descriptors to invalid values.
+    
+    m_fd_send = m_fd_recv = -1;
+
+    if (status != eConnectionStatusSuccess)
+    {
         
-        // 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;
     }
-    return status;
+        
+    m_shutting_down = false;
+    return eConnectionStatusSuccess;
 }
 
 size_t
@@ -340,6 +364,22 @@
         log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...",
                      this, m_fd_recv, dst, dst_len);
 
+    Mutex::Locker locker;
+    bool got_lock = locker.TryLock (m_mutex);
+    if (!got_lock)
+    {
+        if (log)
+            log->Printf ("%p ConnectionFileDescriptor::Read () failed to get the connection lock.",
+                     this);
+        if (error_ptr)
+            error_ptr->SetErrorString ("failed to get the connection lock for read.");
+            
+        status = eConnectionStatusTimedOut;
+        return 0;
+    }
+    else if (m_shutting_down)
+        return eConnectionStatusError;
+    
     ssize_t bytes_read = 0;
 
     status = BytesAvailable (timeout_usec, error_ptr);
@@ -542,7 +582,6 @@
             break;  // Break to close....
         }
 
-        //Disconnect (NULL);
         return 0;
     }
 
@@ -553,6 +592,9 @@
 ConnectionStatus
 ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
 {
+    // Don't need to take the mutex here separately since we are only called from Read.  If we
+    // ever get used more generally we will need to lock here as well.
+    
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
     if (log)
         log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
@@ -641,7 +683,7 @@
                 if (log)
                     log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
                                 this, (int) bytes_read, buffer);
-                
+
                 return eConnectionStatusEndOfFile;
             }
             else





More information about the lldb-commits mailing list