[Lldb-commits] [lldb] r212220 - Add host layer support for pipes.

Greg Clayton gclayton at apple.com
Wed Jul 2 14:10:40 PDT 2014


Author: gclayton
Date: Wed Jul  2 16:10:39 2014
New Revision: 212220

URL: http://llvm.org/viewvc/llvm-project?rev=212220&view=rev
Log:
Add host layer support for pipes.

Windows does support pipes, but they do so in a slightly different way. Added a Host layer which abstracts the use of pipes into a new Pipe class that everyone can use.

Windows benefits include:
- Being able to interrupt running processes when IO is directly hooked up 
- being able to interrupt long running python scripts
- being able to interrupt anything based on ConnectionFileDescriptor


Added:
    lldb/trunk/include/lldb/Host/Pipe.h
    lldb/trunk/source/Host/common/Pipe.cpp
Modified:
    lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
    lldb/trunk/source/Host/common/CMakeLists.txt
    lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h?rev=212220&r1=212219&r2=212220&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original)
+++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Wed Jul  2 16:10:39 2014
@@ -24,6 +24,7 @@
 // Project includes
 #include "lldb/Core/Connection.h"
 #include "lldb/Host/Mutex.h"
+#include "lldb/Host/Pipe.h"
 #include "lldb/Host/Predicate.h"
 
 namespace lldb_private {
@@ -122,8 +123,7 @@ protected:
     FDType m_fd_recv_type;
     std::unique_ptr<SocketAddress> m_udp_send_sockaddr;
     uint32_t m_socket_timeout_usec;
-    int m_pipe_read;            // A pipe that we select on the reading end of along with
-    int m_pipe_write;           // m_fd_recv so we can force ourselves out of the select.
+    Pipe m_pipe;
     Mutex m_mutex;
     Predicate<uint16_t> m_port_predicate; // Used when binding to port zero to wait for the thread that creates the socket, binds and listens to resolve the port number
     bool m_should_close_fd;     // True if this class should close the file descriptor when it goes away.

Added: lldb/trunk/include/lldb/Host/Pipe.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Pipe.h?rev=212220&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Host/Pipe.h (added)
+++ lldb/trunk/include/lldb/Host/Pipe.h Wed Jul  2 16:10:39 2014
@@ -0,0 +1,83 @@
+//===-- Pipe.h --------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Pipe_h_
+#define liblldb_Pipe_h_
+#if defined(__cplusplus)
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class Pipe Pipe.h "lldb/Host/Pipe.h"
+/// @brief A class that abtracts unix style pipes.
+///
+/// A class that abstracts the LLDB core from host pipe functionality.
+//----------------------------------------------------------------------
+class Pipe
+{
+public:
+    static int kInvalidDescriptor;
+    
+    Pipe();
+    
+    ~Pipe();
+    
+    bool
+    Open();
+
+    bool
+    IsValid() const;
+    
+    bool
+    ReadDescriptorIsValid() const;
+
+    bool
+    WriteDescriptorIsValid() const;
+
+    int
+    GetReadFileDescriptor() const;
+    
+    int
+    GetWriteFileDescriptor() const;
+    
+    // Close both descriptors
+    void
+    Close();
+
+    bool
+    CloseReadFileDescriptor();
+    
+    bool
+    CloseWriteFileDescriptor();
+
+    int
+    ReleaseReadFileDescriptor();
+    
+    int
+    ReleaseWriteFileDescriptor();
+
+    size_t
+    Read (void *buf, size_t size);
+
+    size_t
+    Write (const void *buf, size_t size);
+private:
+    int m_fds[2];
+};
+
+} // namespace lldb_private
+
+#endif  // #if defined(__cplusplus)
+#endif  // liblldb_Pipe_h_

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=212220&r1=212219&r2=212220&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Jul  2 16:10:39 2014
@@ -83,6 +83,8 @@
 		2606EDDE184E68940034641B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 260C876910F538E700BB2B04 /* Foundation.framework */; };
 		2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; };
 		260A248E15D06C50009981B0 /* OptionValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A248D15D06C4F009981B0 /* OptionValues.h */; };
+		260A39A619647A3A004B4130 /* Pipe.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A39A519647A3A004B4130 /* Pipe.h */; };
+		260A39A819647A4E004B4130 /* Pipe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260A39A719647A4E004B4130 /* Pipe.cpp */; };
 		260A63171861008E00FECF8E /* IOHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A63161861008E00FECF8E /* IOHandler.h */; };
 		260A63191861009E00FECF8E /* IOHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260A63181861009E00FECF8E /* IOHandler.cpp */; };
 		260CC62E15D04377002BF2E0 /* OptionValueArgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 260CC62115D04377002BF2E0 /* OptionValueArgs.h */; };
@@ -949,6 +951,8 @@
 		26022531115F27FA00A601A2 /* SBFileSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFileSpec.h; path = include/lldb/API/SBFileSpec.h; sourceTree = "<group>"; };
 		26022532115F281400A601A2 /* SBFileSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFileSpec.cpp; path = source/API/SBFileSpec.cpp; sourceTree = "<group>"; };
 		260A248D15D06C4F009981B0 /* OptionValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValues.h; path = include/lldb/Interpreter/OptionValues.h; sourceTree = "<group>"; };
+		260A39A519647A3A004B4130 /* Pipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Pipe.h; path = include/lldb/Host/Pipe.h; sourceTree = "<group>"; };
+		260A39A719647A4E004B4130 /* Pipe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Pipe.cpp; sourceTree = "<group>"; };
 		260A63111860FDB600FECF8E /* Queue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Queue.h; path = include/lldb/Target/Queue.h; sourceTree = "<group>"; };
 		260A63121860FDBD00FECF8E /* QueueItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueItem.h; path = include/lldb/Target/QueueItem.h; sourceTree = "<group>"; };
 		260A63131860FDC700FECF8E /* QueueList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueList.h; path = include/lldb/Target/QueueList.h; sourceTree = "<group>"; };
@@ -1228,6 +1232,7 @@
 		266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystem.cpp; path = source/Target/OperatingSystem.cpp; sourceTree = "<group>"; };
 		266DFE9813FD658300D0C574 /* OperatingSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OperatingSystem.h; path = include/lldb/Target/OperatingSystem.h; sourceTree = "<group>"; };
 		266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = "<group>"; };
+		26709E311964A34000B94724 /* LaunchServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LaunchServices.framework; path = ../../../../../../../System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework; sourceTree = "<group>"; };
 		2670F8111862B44A006B332C /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = /usr/lib/libncurses.dylib; sourceTree = "<absolute>"; };
 		2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = "<group>"; };
 		2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = "<group>"; };
@@ -2161,6 +2166,7 @@
 		08FB7794FE84155DC02AAC07 /* lldb */ = {
 			isa = PBXGroup;
 			children = (
+				26709E311964A34000B94724 /* LaunchServices.framework */,
 				26F5C32810F3DF7D009D5894 /* Libraries */,
 				264E8576159BE51A00E9D7A2 /* Resources */,
 				08FB7795FE84155DC02AAC07 /* Source */,
@@ -3422,6 +3428,7 @@
 				232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */,
 				232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */,
 				A36FF33D17D8E98800244D40 /* OptionParser.h */,
+				260A39A519647A3A004B4130 /* Pipe.h */,
 				26BC7DD610F1B7D500F91463 /* Predicate.h */,
 				26D7E45B13D5E2F9007FD12B /* SocketAddress.h */,
 				26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */,
@@ -3947,6 +3954,7 @@
 				69A01E1C1236C5D400C660B5 /* Host.cpp */,
 				69A01E1E1236C5D400C660B5 /* Mutex.cpp */,
 				A36FF33B17D8E94600244D40 /* OptionParser.cpp */,
+				260A39A719647A4E004B4130 /* Pipe.cpp */,
 				69A01E1F1236C5D400C660B5 /* Symbols.cpp */,
 				268DA873130095ED00C9483A /* Terminal.cpp */,
 				69A01E201236C5D400C660B5 /* TimeValue.cpp */,
@@ -4190,6 +4198,7 @@
 				490A36C2180F0E9300BA31F8 /* PlatformWindows.h in Headers */,
 				26EFC4CE18CFAF0D00865D87 /* ObjectFileJIT.h in Headers */,
 				260CC63615D04377002BF2E0 /* OptionValueFormat.h in Headers */,
+				260A39A619647A3A004B4130 /* Pipe.h in Headers */,
 				26D1804516CEE12500EDFB5B /* KQueue.h in Headers */,
 				260CC63715D04377002BF2E0 /* OptionValueSInt64.h in Headers */,
 				AF061F8C182C980000B6A19C /* HistoryUnwind.h in Headers */,
@@ -4845,6 +4854,7 @@
 				268900D313353E6F00698AC0 /* ClangExternalASTSourceCallbacks.cpp in Sources */,
 				268900D413353E6F00698AC0 /* ClangNamespaceDecl.cpp in Sources */,
 				268900D513353E6F00698AC0 /* CompileUnit.cpp in Sources */,
+				260A39A819647A4E004B4130 /* Pipe.cpp in Sources */,
 				268900D613353E6F00698AC0 /* Declaration.cpp in Sources */,
 				268900D713353E6F00698AC0 /* DWARFCallFrameInfo.cpp in Sources */,
 				268900D813353E6F00698AC0 /* Function.cpp in Sources */,
@@ -5376,6 +5386,7 @@
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
+					"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks",
 				);
 				FRAMEWORK_VERSION = A;
 				GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
@@ -5440,6 +5451,7 @@
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
+					"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks",
 				);
 				FRAMEWORK_VERSION = A;
 				GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
@@ -5778,6 +5790,7 @@
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
+					"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks",
 				);
 				FRAMEWORK_VERSION = A;
 				GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
@@ -6587,6 +6600,7 @@
 				FRAMEWORK_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
+					"$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks",
 				);
 				FRAMEWORK_VERSION = A;
 				GCC_INLINES_ARE_PRIVATE_EXTERN = NO;

Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=212220&r1=212219&r2=212220&view=diff
==============================================================================
--- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original)
+++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Wed Jul  2 16:10:39 2014
@@ -97,9 +97,8 @@ ConnectionFileDescriptor::ConnectionFile
     m_fd_send_type (eFDTypeFile),
     m_fd_recv_type (eFDTypeFile),
     m_udp_send_sockaddr (new SocketAddress()),
-    m_socket_timeout_usec(0),
-    m_pipe_read(-1),
-    m_pipe_write(-1),
+    m_socket_timeout_usec (0),
+    m_pipe (),
     m_mutex (Mutex::eMutexTypeRecursive),
     m_should_close_fd (false),
     m_shutting_down (false)
@@ -118,8 +117,7 @@ ConnectionFileDescriptor::ConnectionFile
     m_fd_recv_type (eFDTypeFile),
     m_udp_send_sockaddr (new SocketAddress()),
     m_socket_timeout_usec(0),
-    m_pipe_read(-1),
-    m_pipe_write(-1),
+    m_pipe (),
     m_mutex (Mutex::eMutexTypeRecursive),
     m_should_close_fd (owns_fd),
     m_shutting_down (false)
@@ -149,13 +147,7 @@ ConnectionFileDescriptor::OpenCommandPip
 
     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
     // Make the command file descriptor here:
-    int filedes[2];
-#ifndef LLDB_DISABLE_POSIX
-    int result = pipe (filedes);
-#else
-    int result = -1;
-#endif
-    if (result != 0)
+    if (!m_pipe.Open())
     {
         if (log)
             log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s",
@@ -163,12 +155,11 @@ ConnectionFileDescriptor::OpenCommandPip
     }
     else
     {
-        m_pipe_read  = filedes[0];
-        m_pipe_write = filedes[1];
         if (log)
             log->Printf ("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d",
-                         static_cast<void*>(this), m_pipe_read,
-                         m_pipe_write);
+                         static_cast<void*>(this),
+                         m_pipe.GetReadFileDescriptor(),
+                         m_pipe.GetWriteFileDescriptor());
     }
 }
 
@@ -180,25 +171,7 @@ ConnectionFileDescriptor::CloseCommandPi
         log->Printf ("%p ConnectionFileDescriptor::CloseCommandPipe()",
                      static_cast<void*>(this));
 
-    if (m_pipe_read != -1)
-    {
-#ifdef _MSC_VER
-        llvm_unreachable("pipe close unsupported in MSVC");
-#else
-        close (m_pipe_read);
-#endif
-        m_pipe_read = -1;
-    }
-
-    if (m_pipe_write != -1)
-    {
-#ifdef _MSC_VER
-        llvm_unreachable("pipe close unsupported in MSVC");
-#else
-        close (m_pipe_write);
-#endif
-        m_pipe_write = -1;
-    }
+    m_pipe.Close();
 }
 
 bool
@@ -364,9 +337,7 @@ ConnectionFileDescriptor::Connect (const
 bool
 ConnectionFileDescriptor::InterruptRead()
 {
-    if (m_pipe_write != -1 )
-        return write (m_pipe_write, "i", 1) == 1;
-    return false;
+    return m_pipe.Write("i", 1) == 1;
 }
 
 ConnectionStatus
@@ -402,13 +373,13 @@ ConnectionFileDescriptor::Disconnect (Er
 
     if (!got_lock)
     {
-        if (m_pipe_write != -1 )
+        if (m_pipe.WriteDescriptorIsValid())
         {
             int result;
-            result = write (m_pipe_write, "q", 1);
+            result = m_pipe.Write("q", 1) == 1;
             if (log)
                 log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, result = %d.",
-                             static_cast<void*>(this), m_pipe_write, result);
+                             static_cast<void*>(this), m_pipe.GetWriteFileDescriptor(), result);
         }
         else if (log)
             log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.",
@@ -757,7 +728,7 @@ ConnectionFileDescriptor::BytesAvailable
     // have another thread change these values out from under us
     // and cause problems in the loop below where like in FS_SET()
     const int data_fd = m_fd_recv;
-    const int pipe_fd = m_pipe_read;
+    const int pipe_fd = m_pipe.GetReadFileDescriptor();
 
     if (data_fd >= 0)
     {
@@ -929,7 +900,7 @@ ConnectionFileDescriptor::BytesAvailable
     // have another thread change these values out from under us
     // and cause problems in the loop below where like in FS_SET()
     const int data_fd = m_fd_recv;
-    const int pipe_fd = m_pipe_read;
+    const int pipe_fd = m_pipe.GetReadFileDescriptor();
     
     // Make sure the file descriptor can be used with select as it
     // must be in range

Modified: lldb/trunk/source/Host/common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/CMakeLists.txt?rev=212220&r1=212219&r2=212220&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/CMakeLists.txt (original)
+++ lldb/trunk/source/Host/common/CMakeLists.txt Wed Jul  2 16:10:39 2014
@@ -13,6 +13,7 @@ add_lldb_library(lldbHostCommon
   NativeProcessProtocol.cpp
   NativeThreadProtocol.cpp
   OptionParser.cpp
+  Pipe.cpp
   ProcessRunLock.cpp
   SocketAddress.cpp
   SoftwareBreakpoint.cpp

Added: lldb/trunk/source/Host/common/Pipe.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Pipe.cpp?rev=212220&view=auto
==============================================================================
--- lldb/trunk/source/Host/common/Pipe.cpp (added)
+++ lldb/trunk/source/Host/common/Pipe.cpp Wed Jul  2 16:10:39 2014
@@ -0,0 +1,172 @@
+//===-- Pipe.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/Pipe.h"
+
+#include <unistd.h>
+
+#ifdef _WIN32
+#include <io.h>
+#include <math.h>   // TODO: not sure if this is needed for windows, remove if not
+#include <process.h>// TODO: not sure if this is needed for windows, remove if not
+#endif
+
+using namespace lldb_private;
+
+int Pipe::kInvalidDescriptor = -1;
+
+enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE
+
+Pipe::Pipe()
+{
+    m_fds[READ] = Pipe::kInvalidDescriptor;
+    m_fds[WRITE] = Pipe::kInvalidDescriptor;
+}
+
+Pipe::~Pipe()
+{
+    Close();
+}
+
+bool
+Pipe::Open()
+{
+    if (IsValid())
+        return true;
+
+#ifdef _WIN32
+    if (::_pipe(m_fds, 256, O_BINARY) == 0)
+        return true
+#else
+    if (::pipe(m_fds) == 0)
+        return true;
+#endif
+    m_fds[READ] = Pipe::kInvalidDescriptor;
+    m_fds[WRITE] = Pipe::kInvalidDescriptor;
+    return false;
+}
+
+int
+Pipe::GetReadFileDescriptor() const
+{
+    return m_fds[READ];
+}
+
+int
+Pipe::GetWriteFileDescriptor() const
+{
+    return m_fds[WRITE];
+}
+
+int
+Pipe::ReleaseReadFileDescriptor()
+{
+    const int fd = m_fds[READ];
+    m_fds[READ] = Pipe::kInvalidDescriptor;
+    return fd;
+}
+
+int
+Pipe::ReleaseWriteFileDescriptor()
+{
+    const int fd = m_fds[WRITE];
+    m_fds[WRITE] = Pipe::kInvalidDescriptor;
+    return fd;
+}
+
+void
+Pipe::Close()
+{
+    CloseReadFileDescriptor();
+    CloseWriteFileDescriptor();
+}
+
+bool
+Pipe::ReadDescriptorIsValid() const
+{
+    return m_fds[READ] != Pipe::kInvalidDescriptor;
+}
+
+bool
+Pipe::WriteDescriptorIsValid() const
+{
+    return m_fds[WRITE] != Pipe::kInvalidDescriptor;
+}
+
+bool
+Pipe::IsValid() const
+{
+    return ReadDescriptorIsValid() && WriteDescriptorIsValid();
+}
+
+bool
+Pipe::CloseReadFileDescriptor()
+{
+    if (ReadDescriptorIsValid())
+    {
+        int err;
+#ifdef _WIN32
+        err = _close(m_fds[READ]);
+#else
+        err = close(m_fds[READ]);
+#endif
+        m_fds[READ] = Pipe::kInvalidDescriptor;
+        return err == 0;
+    }
+    return true;
+}
+
+bool
+Pipe::CloseWriteFileDescriptor()
+{
+    if (WriteDescriptorIsValid())
+    {
+        int err;
+#ifdef _WIN32
+        err = _close(m_fds[WRITE]);
+#else
+        err = close(m_fds[WRITE]);
+#endif
+        m_fds[WRITE] = Pipe::kInvalidDescriptor;
+        return err == 0;
+    }
+    return true;
+}
+
+
+size_t
+Pipe::Read (void *buf, size_t num_bytes)
+{
+    if (ReadDescriptorIsValid())
+    {
+        const int fd = GetReadFileDescriptor();
+#ifdef _WIN32
+        return _read (fd, (char *)buf, num_bytes);
+#else
+        return read (fd, buf, num_bytes);
+#endif
+    }
+    return 0; // Return 0 since errno won't be set if we didn't call read
+}
+
+size_t
+Pipe::Write (const void *buf, size_t num_bytes)
+{
+    if (WriteDescriptorIsValid())
+    {
+        const int fd = GetWriteFileDescriptor();
+#ifdef _WIN32
+        return _write (fd, (char *)buf, num_bytes);
+#else
+        return write (fd, buf, num_bytes);
+#endif
+    }
+    return 0; // Return 0 since errno won't be set if we didn't call write
+}
+

Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=212220&r1=212219&r2=212220&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Wed Jul  2 16:10:39 2014
@@ -32,6 +32,7 @@
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Timer.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/Pipe.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Interpreter/PythonDataObjects.h"
@@ -580,8 +581,7 @@ ScriptInterpreterPython::ExecuteOneLine
         StreamFileSP output_file_sp;
         StreamFileSP error_file_sp;
         Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm");
-        int pipe_fds[2] = { -1, -1 };
-        
+        bool join_read_thread = false;
         if (options.GetEnableIO())
         {
             if (result)
@@ -589,21 +589,17 @@ ScriptInterpreterPython::ExecuteOneLine
                 input_file_sp = debugger.GetInputFile();
                 // Set output to a temporary file so we can forward the results on to the result object
                 
-#ifdef _MSC_VER
-                // pipe is not supported on windows so default to a fail condition
-                int err = 1;
-#else
-                int err = pipe(pipe_fds);
-#endif
-                if (err == 0)
+                Pipe pipe;
+                if (pipe.Open())
                 {
-                    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe_fds[0], true));
+                    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true));
                     if (conn_ap->IsConnected())
                     {
                         output_comm.SetConnection(conn_ap.release());
                         output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream());
                         output_comm.StartReadThread();
-                        FILE *outfile_handle = fdopen (pipe_fds[1], "w");
+                        join_read_thread = true;
+                        FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w");
                         output_file_sp.reset(new StreamFile(outfile_handle, true));
                         error_file_sp = output_file_sp;
                         if (outfile_handle)
@@ -672,7 +668,7 @@ ScriptInterpreterPython::ExecuteOneLine
         if (out_file != err_file)
             ::fflush (err_file);
         
-        if (pipe_fds[0] != -1)
+        if (join_read_thread)
         {
             // Close the write end of the pipe since we are done with our
             // one line script. This should cause the read thread that

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=212220&r1=212219&r2=212220&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Wed Jul  2 16:10:39 2014
@@ -27,6 +27,7 @@
 #include "lldb/Expression/ClangUserExpression.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Host/Pipe.h"
 #include "lldb/Host/Terminal.h"
 #include "lldb/Target/ABI.h"
 #include "lldb/Target/DynamicLoader.h"
@@ -4442,8 +4443,7 @@ public:
         m_process (process),
         m_read_file (),
         m_write_file (write_fd, false),
-        m_pipe_read(),
-        m_pipe_write()
+        m_pipe ()
     {
         m_read_file.SetDescriptor(GetInputFD(), false);
     }
@@ -4457,30 +4457,15 @@ public:
     bool
     OpenPipes ()
     {
-        if (m_pipe_read.IsValid() && m_pipe_write.IsValid())
+        if (m_pipe.IsValid())
             return true;
-
-        int fds[2];
-#ifdef _WIN32
-        // pipe is not supported on windows so default to a fail condition
-        int err = 1;
-#else
-        int err = pipe(fds);
-#endif
-        if (err == 0)
-        {
-            m_pipe_read.SetDescriptor(fds[0], true);
-            m_pipe_write.SetDescriptor(fds[1], true);
-            return true;
-        }
-        return false;
+        return m_pipe.Open();
     }
 
     void
     ClosePipes()
     {
-        m_pipe_read.Close();
-        m_pipe_write.Close();
+        m_pipe.Close();
     }
     
     // Each IOHandler gets to run until it is done. It should read data
@@ -4495,7 +4480,7 @@ public:
             if (OpenPipes())
             {
                 const int read_fd = m_read_file.GetDescriptor();
-                const int pipe_read_fd = m_pipe_read.GetDescriptor();
+                const int pipe_read_fd = m_pipe.GetReadFileDescriptor();
                 TerminalState terminal_state;
                 terminal_state.Save (read_fd, false);
                 Terminal terminal(read_fd);
@@ -4536,17 +4521,18 @@ public:
                         if (FD_ISSET (pipe_read_fd, &read_fdset))
                         {
                             // Consume the interrupt byte
-                            n = 1;
-                            m_pipe_read.Read (&ch, n);
-                            switch (ch)
+                            if (m_pipe.Read (&ch, 1) == 1)
                             {
-                                case 'q':
-                                    SetIsDone(true);
-                                    break;
-                                case 'i':
-                                    if (StateIsRunningState(m_process->GetState()))
-                                        m_process->Halt();
-                                    break;
+                                switch (ch)
+                                {
+                                    case 'q':
+                                        SetIsDone(true);
+                                        break;
+                                    case 'i':
+                                        if (StateIsRunningState(m_process->GetState()))
+                                            m_process->Halt();
+                                        break;
+                                }
                             }
                         }
                     }
@@ -4582,30 +4568,20 @@ public:
     virtual void
     Cancel ()
     {
-        size_t n = 1;
         char ch = 'q';  // Send 'q' for quit
-        m_pipe_write.Write (&ch, n);
+        m_pipe.Write (&ch, 1);
     }
 
     virtual bool
     Interrupt ()
     {
-#ifdef _MSC_VER
-        // Windows doesn't support pipes, so we will send an async interrupt
-        // event to stop the process
-        if (StateIsRunningState(m_process->GetState()))
-            m_process->SendAsyncInterrupt();
-#else
         // Do only things that are safe to do in an interrupt context (like in
         // a SIGINT handler), like write 1 byte to a file descriptor. This will
         // interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte
         // that was written to the pipe and then call m_process->Halt() from a
         // much safer location in code.
-        size_t n = 1;
         char ch = 'i'; // Send 'i' for interrupt
-        m_pipe_write.Write (&ch, n);
-#endif
-        return true;
+        return m_pipe.Write (&ch, 1) == 1;
     }
     
     virtual void
@@ -4618,9 +4594,7 @@ protected:
     Process *m_process;
     File m_read_file;   // Read from this file (usually actual STDIN for LLDB
     File m_write_file;  // Write to this file (usually the master pty for getting io to debuggee)
-    File m_pipe_read;
-    File m_pipe_write;
-
+    Pipe m_pipe;
 };
 
 void





More information about the lldb-commits mailing list