[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