[Lldb-commits] [lldb] r225849 - Extend PipePosix with support for named pipes/timeout-based IO and integrate it with GDBRemoteCommunication / lldb-gdbserver.

Oleksiy Vyalov ovyalov at google.com
Tue Jan 13 15:19:40 PST 2015


Author: ovyalov
Date: Tue Jan 13 17:19:40 2015
New Revision: 225849

URL: http://llvm.org/viewvc/llvm-project?rev=225849&view=rev
Log:
Extend PipePosix with support for named pipes/timeout-based IO and integrate it with GDBRemoteCommunication / lldb-gdbserver.

http://reviews.llvm.org/D6954


Added:
    lldb/trunk/source/Host/common/PipeBase.cpp
Modified:
    lldb/trunk/include/lldb/Host/PipeBase.h
    lldb/trunk/include/lldb/Host/posix/PipePosix.h
    lldb/trunk/include/lldb/Host/windows/PipeWindows.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/Host/CMakeLists.txt
    lldb/trunk/source/Host/posix/PipePosix.cpp
    lldb/trunk/source/Host/windows/PipeWindows.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
    lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp

Modified: lldb/trunk/include/lldb/Host/PipeBase.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/PipeBase.h?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/PipeBase.h (original)
+++ lldb/trunk/include/lldb/Host/PipeBase.h Tue Jan 13 17:19:40 2015
@@ -21,12 +21,16 @@ namespace lldb_private
 class PipeBase
 {
   public:
-    virtual ~PipeBase() {}
+    virtual ~PipeBase();
 
     virtual Error CreateNew(bool child_process_inherit) = 0;
     virtual Error CreateNew(llvm::StringRef name, bool child_process_inherit) = 0;
-    virtual Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) = 0;
-    virtual Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit) = 0;
+
+    Error OpenAsReader(llvm::StringRef name, bool child_process_inherit);
+    virtual Error OpenAsReaderWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) = 0;
+
+    Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit);
+    virtual Error OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) = 0;
 
     virtual bool CanRead() const = 0;
     virtual bool CanWrite() const = 0;
@@ -39,9 +43,12 @@ class PipeBase
     // Close both descriptors
     virtual void Close() = 0;
 
+    // Delete named pipe.
+    virtual Error Delete(llvm::StringRef name) = 0;
+
     virtual Error Write(const void *buf, size_t size, size_t &bytes_written) = 0;
-    virtual Error Read(void *buf, size_t size, size_t &bytes_read) = 0;
-    virtual Error ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &timeout, size_t &bytes_read) = 0;
+    virtual Error ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) = 0;
+    Error Read(void *buf, size_t size, size_t &bytes_read);
 };
 }
 

Modified: lldb/trunk/include/lldb/Host/posix/PipePosix.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/posix/PipePosix.h?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/posix/PipePosix.h (original)
+++ lldb/trunk/include/lldb/Host/posix/PipePosix.h Tue Jan 13 17:19:40 2015
@@ -31,29 +31,46 @@ public:
 
     ~PipePosix() override;
 
-    Error CreateNew(bool child_process_inherit) override;
-    Error CreateNew(llvm::StringRef name, bool child_process_inherit) override;
-    Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) override;
-    Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit) override;
-
-    bool CanRead() const override;
-    bool CanWrite() const override;
-
-    int GetReadFileDescriptor() const override;
-    int GetWriteFileDescriptor() const override;
-    int ReleaseReadFileDescriptor() override;
-    int ReleaseWriteFileDescriptor() override;
+    Error
+    CreateNew(bool child_process_inherit) override;
+    Error
+    CreateNew(llvm::StringRef name, bool child_process_inherit) override;
+    Error
+    OpenAsReaderWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override;
+    Error
+    OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override;
+
+    bool
+    CanRead() const override;
+    bool
+    CanWrite() const override;
+
+    int
+    GetReadFileDescriptor() const override;
+    int
+    GetWriteFileDescriptor() const override;
+    int
+    ReleaseReadFileDescriptor() override;
+    int
+    ReleaseWriteFileDescriptor() override;
 
     // Close both descriptors
-    void Close() override;
+    void
+    Close() override;
 
-    Error Write(const void *buf, size_t size, size_t &bytes_written) override;
-    Error Read(void *buf, size_t size, size_t &bytes_read) override;
-    Error ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &timeout, size_t &bytes_read) override;
+    Error
+    Delete(llvm::StringRef name) override;
+
+    Error
+    Write(const void *buf, size_t size, size_t &bytes_written) override;
+    Error
+    ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) override;
 
 private:
-  void CloseReadFileDescriptor();
-  void CloseWriteFileDescriptor();
+    void
+    CloseReadFileDescriptor();
+    void
+    CloseWriteFileDescriptor();
 
     int m_fds[2];
 };

Modified: lldb/trunk/include/lldb/Host/windows/PipeWindows.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/windows/PipeWindows.h?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/windows/PipeWindows.h (original)
+++ lldb/trunk/include/lldb/Host/windows/PipeWindows.h Tue Jan 13 17:19:40 2015
@@ -31,8 +31,8 @@ class PipeWindows : public PipeBase
 
     Error CreateNew(bool child_process_inherit) override;
     Error CreateNew(llvm::StringRef name, bool child_process_inherit) override;
-    Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) override;
-    Error OpenAsWriter(llvm::StringRef name, bool child_process_inherit) override;
+    Error OpenAsReaderWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override;
+    Error OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override;
 
     bool CanRead() const override;
     bool CanWrite() const override;
@@ -44,9 +44,10 @@ class PipeWindows : public PipeBase
 
     void Close() override;
 
+    Error Delete(llvm::StringRef name) override;
+
     Error Write(const void *buf, size_t size, size_t &bytes_written) override;
-    Error Read(void *buf, size_t size, size_t &bytes_read) override;
-    Error ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &timeout, size_t &bytes_read) override;
+    Error ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) override;
 
     // PipeWindows specific methods.  These allow access to the underlying OS handle.
     HANDLE GetReadNativeHandle();

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Jan 13 17:19:40 2015
@@ -77,6 +77,7 @@
 		23EFE38B193D1AEC00E54E54 /* SBTypeEnumMember.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */; };
 		23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */; };
 		25420ECD1A6490B8009ADBCB /* OptionValueChar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */; };
+		25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ED11A649D88009ADBCB /* PipeBase.cpp */; };
 		260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
 		260157C71885F52500F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
 		260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
@@ -1031,6 +1032,7 @@
 		23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContextRegisterInfo.cpp; path = source/Target/NativeRegisterContextRegisterInfo.cpp; sourceTree = "<group>"; };
 		25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueChar.cpp; path = source/Interpreter/OptionValueChar.cpp; sourceTree = "<group>"; };
 		25420ECE1A64911B009ADBCB /* OptionValueChar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionValueChar.h; path = include/lldb/Interpreter/OptionValueChar.h; sourceTree = "<group>"; };
+		25420ED11A649D88009ADBCB /* PipeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipeBase.cpp; sourceTree = "<group>"; };
 		260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = "<absolute>"; };
 		260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = "<group>"; };
 		260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = "<group>"; };
@@ -4319,6 +4321,7 @@
 		69A01E1A1236C5D400C660B5 /* common */ = {
 			isa = PBXGroup;
 			children = (
+				25420ED11A649D88009ADBCB /* PipeBase.cpp */,
 				26CFDCA2186163A4000E63E5 /* Editline.cpp */,
 				260C6EA213011581005E16B0 /* File.cpp */,
 				26FA43171301048600E71120 /* FileSpec.cpp */,
@@ -5261,6 +5264,7 @@
 				2689007113353E1A00698AC0 /* Host.cpp in Sources */,
 				2635879417822FC2004C30BA /* SymbolVendorELF.cpp in Sources */,
 				2689007213353E1A00698AC0 /* Mutex.cpp in Sources */,
+				25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */,
 				2689007313353E1A00698AC0 /* Symbols.cpp in Sources */,
 				26474CBC18D0CB2D0073DEBA /* RegisterContextMach_arm.cpp in Sources */,
 				2689007413353E1A00698AC0 /* Terminal.cpp in Sources */,

Modified: lldb/trunk/source/Host/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/CMakeLists.txt?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/source/Host/CMakeLists.txt (original)
+++ lldb/trunk/source/Host/CMakeLists.txt Tue Jan 13 17:19:40 2015
@@ -21,6 +21,7 @@ add_host_subdirectory(common
   common/NativeProcessProtocol.cpp
   common/NativeThreadProtocol.cpp
   common/OptionParser.cpp
+  common/PipeBase.cpp
   common/ProcessRunLock.cpp
   common/Socket.cpp
   common/SocketAddress.cpp

Added: lldb/trunk/source/Host/common/PipeBase.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/PipeBase.cpp?rev=225849&view=auto
==============================================================================
--- lldb/trunk/source/Host/common/PipeBase.cpp (added)
+++ lldb/trunk/source/Host/common/PipeBase.cpp Tue Jan 13 17:19:40 2015
@@ -0,0 +1,33 @@
+//===-- source/Host/common/PipeBase.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/PipeBase.h"
+
+using namespace lldb_private;
+
+
+PipeBase::~PipeBase() = default;
+
+Error
+PipeBase::OpenAsReader(llvm::StringRef name, bool child_process_inherit)
+{
+    return OpenAsReaderWithTimeout(name, child_process_inherit, std::chrono::microseconds::zero());
+}
+
+Error
+PipeBase::OpenAsWriter(llvm::StringRef name, bool child_process_inherit)
+{
+    return OpenAsWriterWithTimeout(name, child_process_inherit, std::chrono::microseconds::zero());
+}
+
+Error
+PipeBase::Read(void *buf, size_t size, size_t &bytes_read)
+{
+    return ReadWithTimeout(buf, size, std::chrono::microseconds::zero(), bytes_read);
+}

Modified: lldb/trunk/source/Host/posix/PipePosix.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/posix/PipePosix.cpp?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/source/Host/posix/PipePosix.cpp (original)
+++ lldb/trunk/source/Host/posix/PipePosix.cpp Tue Jan 13 17:19:40 2015
@@ -8,11 +8,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/posix/PipePosix.h"
+#include "lldb/Host/FileSystem.h"
+
+#include <functional>
+#include <thread>
 
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 
 using namespace lldb;
 using namespace lldb_private;
@@ -32,6 +37,8 @@ enum PIPES { READ, WRITE }; // Constants
 namespace
 {
 
+constexpr auto OPEN_WRITER_SLEEP_TIMEOUT_MSECS = 100;
+
 #if defined(FD_CLOEXEC) && !PIPE2_SUPPORTED
 bool SetCloexecFlag(int fd)
 {
@@ -42,6 +49,79 @@ bool SetCloexecFlag(int fd)
 }
 #endif
 
+std::chrono::time_point<std::chrono::steady_clock>
+Now()
+{
+    return std::chrono::steady_clock::now();
+}
+
+Error
+SelectIO(int handle, bool is_read, const std::function<Error(bool&)> &io_handler, const std::chrono::microseconds &timeout)
+{
+    Error error;
+    fd_set fds;
+    bool done = false;
+
+    using namespace std::chrono;
+
+    const auto finish_time = Now() + timeout;
+
+    while (!done)
+    {
+        struct timeval tv = {0, 0};
+        if (timeout != microseconds::zero())
+        {
+            const auto remaining_dur = duration_cast<microseconds>(finish_time - Now());
+            if (remaining_dur.count() <= 0)
+            {
+                error.SetErrorString("timeout exceeded");
+                break;
+            }
+            const auto dur_secs = duration_cast<seconds>(remaining_dur);
+            const auto dur_usecs = remaining_dur % seconds(1);
+
+            tv.tv_sec = dur_secs.count();
+            tv.tv_usec = dur_usecs.count();
+        }
+        else
+            tv.tv_sec = 1;
+
+        FD_ZERO(&fds);
+        FD_SET(handle, &fds);
+
+        const auto retval = ::select(handle + 1,
+                                     (is_read) ? &fds : nullptr,
+                                     (is_read) ? nullptr : &fds,
+                                     nullptr, &tv);
+        if (retval == -1)
+        {
+            if (errno == EINTR)
+                continue;
+            error.SetErrorToErrno();
+            break;
+        }
+        if (retval == 0)
+        {
+            error.SetErrorString("timeout exceeded");
+            break;
+        }
+        if (!FD_ISSET(handle, &fds))
+        {
+            error.SetErrorString("invalid state");
+            break;
+        }
+
+        error = io_handler(done);
+        if (error.Fail())
+        {
+          if (error.GetError() == EINTR)
+              continue;
+            break;
+        }
+    }
+    return error;
+}
+
 }
 
 PipePosix::PipePosix()
@@ -58,13 +138,10 @@ PipePosix::~PipePosix()
 Error
 PipePosix::CreateNew(bool child_processes_inherit)
 {
-    Error error;
     if (CanRead() || CanWrite())
-    {
-        error.SetError(EINVAL, eErrorTypePOSIX);
-        return error;
-    }
+        return Error(EINVAL, eErrorTypePOSIX);
 
+    Error error;
 #if PIPE2_SUPPORTED
     if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0)
         return error;
@@ -86,49 +163,85 @@ PipePosix::CreateNew(bool child_processe
     }
 #endif
 
+    error.SetErrorToErrno();
     m_fds[READ] = PipePosix::kInvalidDescriptor;
     m_fds[WRITE] = PipePosix::kInvalidDescriptor;
-    error.SetErrorToErrno();
     return error;
 }
 
 Error
 PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit)
 {
-    Error error;
     if (CanRead() || CanWrite())
-        error.SetErrorString("Pipe is already opened");
-    else if (name.empty())
-        error.SetErrorString("Cannot create named pipe with empty name.");
-    else
-        error.SetErrorString("Not implemented");
+        return Error("Pipe is already opened");
+
+    Error error;
+    if (::mkfifo(name.data(), 0660) != 0)
+        error.SetErrorToErrno();
+
     return error;
 }
 
 Error
-PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit)
+PipePosix::OpenAsReaderWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout)
 {
-    Error error;
     if (CanRead() || CanWrite())
-        error.SetErrorString("Pipe is already opened");
-    else if (name.empty())
-        error.SetErrorString("Cannot open named pipe with empty name.");
+        return Error("Pipe is already opened");
+
+    int flags = O_RDONLY | O_NONBLOCK;
+    if (!child_process_inherit)
+        flags |= O_CLOEXEC;
+
+    Error error;
+    int fd = ::open(name.data(), flags);
+    if (fd != -1)
+        m_fds[READ] = fd;
     else
-        error.SetErrorString("Not implemented");
+        error.SetErrorToErrno();
+
     return error;
 }
 
 Error
-PipePosix::OpenAsWriter(llvm::StringRef name, bool child_process_inherit)
+PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout)
 {
-    Error error;
     if (CanRead() || CanWrite())
-        error.SetErrorString("Pipe is already opened");
-    else if (name.empty())
-        error.SetErrorString("Cannot create named pipe with empty name.");
-    else
-        error.SetErrorString("Not implemented");
-    return error;
+        return Error("Pipe is already opened");
+
+    int flags = O_WRONLY | O_NONBLOCK;
+    if (!child_process_inherit)
+        flags |= O_CLOEXEC;
+
+    using namespace std::chrono;
+    const auto finish_time = Now() + timeout;
+
+    while (!CanWrite())
+    {
+        if (timeout != microseconds::zero())
+        {
+            const auto dur = duration_cast<microseconds>(finish_time - Now()).count();
+            if (dur <= 0)
+                return Error("timeout exceeded - reader hasn't opened so far");
+        }
+
+        errno = 0;
+        int fd = ::open(name.data(), flags);
+        if (fd == -1)
+        {
+            const auto errno_copy = errno;
+            // We may get ENXIO if a reader side of the pipe hasn't opened yet.
+            if (errno_copy != ENXIO)
+                return Error(errno_copy, eErrorTypePOSIX);
+
+            std::this_thread::sleep_for(milliseconds(OPEN_WRITER_SLEEP_TIMEOUT_MSECS));
+        }
+        else
+        {
+            m_fds[WRITE] = fd;
+        }
+    }
+
+    return Error();
 }
 
 int
@@ -166,6 +279,12 @@ PipePosix::Close()
     CloseWriteFileDescriptor();
 }
 
+Error
+PipePosix::Delete(llvm::StringRef name)
+{
+    return FileSystem::Unlink(name.data());
+}
+
 bool
 PipePosix::CanRead() const
 {
@@ -183,8 +302,7 @@ PipePosix::CloseReadFileDescriptor()
 {
     if (CanRead())
     {
-        int err;
-        err = close(m_fds[READ]);
+        close(m_fds[READ]);
         m_fds[READ] = PipePosix::kInvalidDescriptor;
     }
 }
@@ -194,59 +312,67 @@ PipePosix::CloseWriteFileDescriptor()
 {
     if (CanWrite())
     {
-        int err;
-        err = close(m_fds[WRITE]);
+        close(m_fds[WRITE]);
         m_fds[WRITE] = PipePosix::kInvalidDescriptor;
     }
 }
 
 Error
-PipePosix::Read(void *buf, size_t num_bytes, size_t &bytes_read)
+PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read)
 {
     bytes_read = 0;
-    Error error;
+    if (!CanRead())
+        return Error(EINVAL, eErrorTypePOSIX);
 
-    if (CanRead())
-    {
-        const int fd = GetReadFileDescriptor();
-        int result = read(fd, buf, num_bytes);
-        if (result >= 0)
-            bytes_read = result;
-        else
-            error.SetErrorToErrno();
-    }
-    else
-        error.SetError(EINVAL, eErrorTypePOSIX);
-
-    return error;
-}
-
-Error
-PipePosix::ReadWithTimeout(void *buf, size_t num_bytes, const std::chrono::milliseconds &duration, size_t &bytes_read)
-{
-    bytes_read = 0;
-    Error error;
-    error.SetErrorString("Not implemented");
-    return error;
+    auto handle = GetReadFileDescriptor();
+    return SelectIO(handle,
+                    true,
+                    [=, &bytes_read](bool &done)
+                    {
+                      Error error;
+                      auto result = ::read(handle,
+                                           reinterpret_cast<char*>(buf) + bytes_read,
+                                           size - bytes_read);
+                      if (result != -1)
+                      {
+                          bytes_read += result;
+                          if (bytes_read == size || result == 0)
+                              done = true;
+                      }
+                      else
+                          error.SetErrorToErrno();
+
+                      return error;
+                  },
+                  timeout);
 }
 
 Error
-PipePosix::Write(const void *buf, size_t num_bytes, size_t &bytes_written)
+PipePosix::Write(const void *buf, size_t size, size_t &bytes_written)
 {
     bytes_written = 0;
-    Error error;
-
-    if (CanWrite())
-    {
-        const int fd = GetWriteFileDescriptor();
-        int result = write(fd, buf, num_bytes);
-        if (result >= 0)
-            bytes_written = result;
-        else
-            error.SetErrorToErrno();
-    }
-    else
-        error.SetError(EINVAL, eErrorTypePOSIX);
+    if (!CanWrite())
+        return Error(EINVAL, eErrorTypePOSIX);
 
-    return error;
+    auto handle = GetWriteFileDescriptor();
+    return SelectIO(handle,
+                    false,
+                    [=, &bytes_written](bool &done)
+                    {
+                        Error error;
+                        auto result = ::write(handle,
+                                              reinterpret_cast<const char*>(buf) + bytes_written,
+                                              size - bytes_written);
+                        if (result != -1)
+                        {
+                            bytes_written += result;
+                            if (bytes_written == size)
+                                done = true;
+                        }
+                        else
+                            error.SetErrorToErrno();
+
+                        return error;
+                    },
+                    std::chrono::microseconds::zero());
 }

Modified: lldb/trunk/source/Host/windows/PipeWindows.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/PipeWindows.cpp?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/source/Host/windows/PipeWindows.cpp (original)
+++ lldb/trunk/source/Host/windows/PipeWindows.cpp Tue Jan 13 17:19:40 2015
@@ -90,7 +90,7 @@ PipeWindows::CreateNew(llvm::StringRef n
 }
 
 Error
-PipeWindows::OpenAsReader(llvm::StringRef name, bool child_process_inherit)
+PipeWindows::OpenAsReaderWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout)
 {
     if (CanRead() || CanWrite())
         return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
@@ -99,7 +99,7 @@ PipeWindows::OpenAsReader(llvm::StringRe
 }
 
 Error
-PipeWindows::OpenAsWriter(llvm::StringRef name, bool child_process_inherit)
+PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout)
 {
     if (CanRead() || CanWrite())
         return Error(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
@@ -217,6 +217,12 @@ PipeWindows::Close()
     CloseWriteEndpoint();
 }
 
+Error
+PipeWindows::Delete(llvm::StringRef name)
+{
+    return Error();
+}
+
 bool
 PipeWindows::CanRead() const
 {
@@ -242,13 +248,7 @@ PipeWindows::GetWriteNativeHandle()
 }
 
 Error
-PipeWindows::Read(void *buf, size_t size, size_t &bytes_read)
-{
-    return ReadWithTimeout(buf, size, std::chrono::milliseconds::zero(), bytes_read);
-}
-
-Error
-PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::milliseconds &duration, size_t &bytes_read)
+PipeWindows::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &duration, size_t &bytes_read)
 {
     if (!CanRead())
         return Error(ERROR_INVALID_HANDLE, eErrorTypeWin32);
@@ -259,7 +259,7 @@ PipeWindows::ReadWithTimeout(void *buf,
     if (!result && GetLastError() != ERROR_IO_PENDING)
         return Error(::GetLastError(), eErrorTypeWin32);
 
-    DWORD timeout = (duration == std::chrono::milliseconds::zero()) ? INFINITE : duration.count();
+    DWORD timeout = (duration == std::chrono::microseconds::zero()) ? INFINITE : duration.count() * 1000;
     DWORD wait_result = ::WaitForSingleObject(m_read_overlapped.hEvent, timeout);
     if (wait_result != WAIT_OBJECT_0)
     {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Tue Jan 13 17:19:40 2015
@@ -22,9 +22,9 @@
 #include "lldb/Core/StreamString.h"
 #include "lldb/Host/ConnectionFileDescriptor.h"
 #include "lldb/Host/FileSpec.h"
-#include "lldb/Host/FileSystem.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Pipe.h"
 #include "lldb/Host/Socket.h"
 #include "lldb/Host/ThreadLauncher.h"
 #include "lldb/Host/TimeValue.h"
@@ -763,6 +763,7 @@ GDBRemoteCommunication::StartDebugserver
 
         char named_pipe_path[PATH_MAX];
         named_pipe_path[0] = '\0';
+        Pipe port_named_pipe;
 
         bool listen = false;
         if (host_and_port[0])
@@ -788,15 +789,11 @@ GDBRemoteCommunication::StartDebugserver
 
                 if (::mktemp (named_pipe_path))
                 {
-#if defined(_WIN32)
-                    if ( false )
-#else
-                    if (::mkfifo(named_pipe_path, 0600) == 0)
-#endif
-                    {
-                        debugserver_args.AppendArgument("--named-pipe");
-                        debugserver_args.AppendArgument(named_pipe_path);
-                    }
+                    error = port_named_pipe.CreateNew(named_pipe_path, false);
+                    if (error.Fail())
+                        return error;
+                    debugserver_args.AppendArgument("--named-pipe");
+                    debugserver_args.AppendArgument(named_pipe_path);
                 }
             }
             else
@@ -879,20 +876,41 @@ GDBRemoteCommunication::StartDebugserver
         {
             if (named_pipe_path[0])
             {
-                File name_pipe_file;
-                error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
+                const auto timeout = std::chrono::microseconds(10 * 1000000);
+                error = port_named_pipe.OpenAsReaderWithTimeout(named_pipe_path, false, timeout);
                 if (error.Success())
                 {
                     char port_cstr[256];
                     port_cstr[0] = '\0';
                     size_t num_bytes = sizeof(port_cstr);
-                    error = name_pipe_file.Read(port_cstr, num_bytes);
-                    assert (error.Success());
-                    assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
-                    out_port = Args::StringToUInt32(port_cstr, 0);
-                    name_pipe_file.Close();
+                    // Read port from pipe with 10 second timeout.
+                    error = port_named_pipe.ReadWithTimeout(port_cstr, num_bytes, timeout, num_bytes);
+                    if (error.Success())
+                    {
+                        assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
+                        out_port = Args::StringToUInt32(port_cstr, 0);
+                        if (log)
+                            log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port);
+                    }
+                    else
+                    {
+                        if (log)
+                            log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString());
+
+                    }
+                    port_named_pipe.Close();
+                }
+                else
+                {
+                    if (log)
+                        log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString());
+                }
+                const auto err = port_named_pipe.Delete(named_pipe_path);
+                if (err.Fail())
+                {
+                    if (log)
+                        log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString());
                 }
-                FileSystem::Unlink(named_pipe_path);
             }
             else if (listen)
             {

Modified: lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp?rev=225849&r1=225848&r2=225849&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp (original)
+++ lldb/trunk/tools/lldb-gdbserver/lldb-gdbserver.cpp Tue Jan 13 17:19:40 2015
@@ -31,6 +31,7 @@
 #include "lldb/Core/StreamFile.h"
 #include "lldb/Host/ConnectionFileDescriptor.h"
 #include "lldb/Host/HostThread.h"
+#include "lldb/Host/Pipe.h"
 #include "lldb/Host/OptionParser.h"
 #include "lldb/Host/Socket.h"
 #include "lldb/Host/ThreadLauncher.h"
@@ -309,24 +310,18 @@ JoinListenThread ()
 Error
 writePortToPipe (const char *const named_pipe_path, const uint16_t port)
 {
-    Error error;
-
-    // FIXME use new generic named pipe support.
-    int fd = ::open (named_pipe_path, O_WRONLY);
-    if (fd == -1)
-    {
-        error.SetErrorToErrno ();
+    Pipe port_name_pipe;
+    // Wait for 10 seconds for pipe to be opened.
+    auto error = port_name_pipe.OpenAsWriterWithTimeout (named_pipe_path, false, std::chrono::microseconds (10 * 1000000));
+    if (error.Fail ())
         return error;
-    }
 
     char port_str[64];
-    const ssize_t port_str_len = ::snprintf (port_str, sizeof(port_str), "%u", port);
-    // Write the port number as a C string with the NULL terminator.
-    if (::write (fd, port_str, port_str_len + 1) == -1)
-        error.SetErrorToErrno ();
+    const auto port_str_len = ::snprintf (port_str, sizeof (port_str), "%u", port);
 
-    close (fd);
-    return error;
+    size_t bytes_written = 0;
+    // Write the port number as a C string with the NULL terminator.
+    return port_name_pipe.Write (port_str, port_str_len + 1, bytes_written);
 }
 
 void





More information about the lldb-commits mailing list