diff options
-rw-r--r-- | lldb/include/lldb/Core/ConnectionFileDescriptor.h | 9 | ||||
-rw-r--r-- | lldb/source/Core/ConnectionFileDescriptor.cpp | 155 |
2 files changed, 112 insertions, 52 deletions
diff --git a/lldb/include/lldb/Core/ConnectionFileDescriptor.h b/lldb/include/lldb/Core/ConnectionFileDescriptor.h index b2a29d6c6e2..f7710718b8b 100644 --- a/lldb/include/lldb/Core/ConnectionFileDescriptor.h +++ b/lldb/include/lldb/Core/ConnectionFileDescriptor.h @@ -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 @@ public: protected: + void + InitializeCommandFileDescriptor (); + + void + CloseCommandFileDescriptor (); + lldb::ConnectionStatus BytesAvailable (uint32_t timeout_usec, Error *error_ptr); @@ -105,6 +112,8 @@ protected: 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 diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index 538f84be797..0345def0ac5 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -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 @@ ConnectionFileDescriptor::ConnectionFileDescriptor () : 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 @@ ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) : 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 @@ ConnectionFileDescriptor::~ConnectionFileDescriptor () 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 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) if (log) log->Printf ("%p ConnectionFileDescriptor::Connect (url = '%s')", this, s); + InitializeCommandFileDescriptor(); + if (s && s[0]) { char *end = NULL; @@ -157,7 +204,7 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) 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 @@ ConnectionFileDescriptor::Disconnect (Error *error_ptr) 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 @@ ConnectionFileDescriptor::Read (void *dst, 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 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt 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 @@ ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_pt } 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; } } |