diff options
author | Zachary Turner <zturner@google.com> | 2014-12-17 18:02:19 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2014-12-17 18:02:19 +0000 |
commit | 0b9d3eefdbf2c9bb50e139c5272b413e8227d842 (patch) | |
tree | fa6ac73e658e94d59432d15646ce1416662954f0 /lldb/source/Host/posix/PipePosix.cpp | |
parent | 06b2c54db9132bc7b6e599c2a3252ea7f2a8b33b (diff) | |
download | bcm5719-llvm-0b9d3eefdbf2c9bb50e139c5272b413e8227d842.tar.gz bcm5719-llvm-0b9d3eefdbf2c9bb50e139c5272b413e8227d842.zip |
Enhance the Pipe interface for better portability.
This patch makes a number of improvements to the Pipe interface.
1) An interface (PipeBase) is provided which exposes pure virtual
methods for any implementation of Pipe to override. While not
strictly necessary, this helps catch errors where the interfaces
are out of sync.
2) All methods return lldb_private::Error instead of returning bool
or void. This allows richer error information to be propagated
up to LLDB.
3) A new ReadWithTimeout() method is exposed in the base class and
implemented on Windows.
4) Support for both named and anonymous pipes is exposed through the
base interface and implemented on Windows. For creating a new
pipe, both named and anonymous pipes are supported, and for
opening an existing pipe, only named pipes are supported.
New methods described in points #3 and #4 are stubbed out on posix,
but fully implemented on Windows. These should be implemented by
someone on the linux / mac / bsd side.
Reviewed by: Greg Clayton, Oleksiy Vyalov
Differential Revision: http://reviews.llvm.org/D6686
llvm-svn: 224442
Diffstat (limited to 'lldb/source/Host/posix/PipePosix.cpp')
-rw-r--r-- | lldb/source/Host/posix/PipePosix.cpp | 187 |
1 files changed, 130 insertions, 57 deletions
diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp index bf6863c5411..1dbba96b9b1 100644 --- a/lldb/source/Host/posix/PipePosix.cpp +++ b/lldb/source/Host/posix/PipePosix.cpp @@ -9,18 +9,25 @@ #include "lldb/Host/posix/PipePosix.h" -#include <unistd.h> +#include <errno.h> #include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +using namespace lldb; using namespace lldb_private; -int Pipe::kInvalidDescriptor = -1; +int PipePosix::kInvalidDescriptor = -1; enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE // pipe2 is supported by Linux, FreeBSD v10 and higher. // TODO: Add more platforms that support pipe2. -#define PIPE2_SUPPORTED defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) +#define PIPE2_SUPPORTED 1 +#else +#define PIPE2_SUPPORTED 0 +#endif namespace { @@ -37,26 +44,33 @@ bool SetCloexecFlag(int fd) } -Pipe::Pipe() +PipePosix::PipePosix() { - m_fds[READ] = Pipe::kInvalidDescriptor; - m_fds[WRITE] = Pipe::kInvalidDescriptor; + m_fds[READ] = PipePosix::kInvalidDescriptor; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; } -Pipe::~Pipe() +PipePosix::~PipePosix() { Close(); } -bool -Pipe::Open(bool child_processes_inherit) +Error +PipePosix::CreateNew(bool child_processes_inherit) { - if (IsValid()) - return true; + Error error; + if (CanRead() || CanWrite()) + { + error.SetError(EINVAL, eErrorTypePOSIX); + return error; + } #if PIPE2_SUPPORTED if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0) - return true; + { + error.SetErrorToErrno(); + return error; + } #else if (::pipe(m_fds) == 0) { @@ -65,118 +79,177 @@ Pipe::Open(bool child_processes_inherit) { if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) { + error.SetErrorToErrno(); Close(); - return false; + return error; } } #endif - return true; + return error; } #endif - m_fds[READ] = Pipe::kInvalidDescriptor; - m_fds[WRITE] = Pipe::kInvalidDescriptor; - return false; + 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; +} + +Error +PipePosix::OpenAsReader(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 open named pipe with empty name."); + else + error.SetErrorString("Not implemented"); + return error; +} + +Error +PipePosix::OpenAsWriter(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; } int -Pipe::GetReadFileDescriptor() const +PipePosix::GetReadFileDescriptor() const { return m_fds[READ]; } int -Pipe::GetWriteFileDescriptor() const +PipePosix::GetWriteFileDescriptor() const { return m_fds[WRITE]; } int -Pipe::ReleaseReadFileDescriptor() +PipePosix::ReleaseReadFileDescriptor() { const int fd = m_fds[READ]; - m_fds[READ] = Pipe::kInvalidDescriptor; + m_fds[READ] = PipePosix::kInvalidDescriptor; return fd; } int -Pipe::ReleaseWriteFileDescriptor() +PipePosix::ReleaseWriteFileDescriptor() { const int fd = m_fds[WRITE]; - m_fds[WRITE] = Pipe::kInvalidDescriptor; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; return fd; } void -Pipe::Close() +PipePosix::Close() { CloseReadFileDescriptor(); CloseWriteFileDescriptor(); } bool -Pipe::ReadDescriptorIsValid() const -{ - return m_fds[READ] != Pipe::kInvalidDescriptor; -} - -bool -Pipe::WriteDescriptorIsValid() const +PipePosix::CanRead() const { - return m_fds[WRITE] != Pipe::kInvalidDescriptor; + return m_fds[READ] != PipePosix::kInvalidDescriptor; } bool -Pipe::IsValid() const +PipePosix::CanWrite() const { - return ReadDescriptorIsValid() && WriteDescriptorIsValid(); + return m_fds[WRITE] != PipePosix::kInvalidDescriptor; } -bool -Pipe::CloseReadFileDescriptor() +void +PipePosix::CloseReadFileDescriptor() { - if (ReadDescriptorIsValid()) + if (CanRead()) { int err; err = close(m_fds[READ]); - m_fds[READ] = Pipe::kInvalidDescriptor; - return err == 0; + m_fds[READ] = PipePosix::kInvalidDescriptor; } - return true; } -bool -Pipe::CloseWriteFileDescriptor() +void +PipePosix::CloseWriteFileDescriptor() { - if (WriteDescriptorIsValid()) + if (CanWrite()) { int err; err = close(m_fds[WRITE]); - m_fds[WRITE] = Pipe::kInvalidDescriptor; - return err == 0; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; } - return true; } - -size_t -Pipe::Read (void *buf, size_t num_bytes) +Error +PipePosix::Read(void *buf, size_t num_bytes, size_t &bytes_read) { - if (ReadDescriptorIsValid()) + bytes_read = 0; + Error error; + + if (CanRead()) { const int fd = GetReadFileDescriptor(); - return read (fd, buf, num_bytes); + int result = read(fd, buf, num_bytes); + if (result >= 0) + bytes_read = result; + else + error.SetErrorToErrno(); } - return 0; // Return 0 since errno won't be set if we didn't call read + 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; } -size_t -Pipe::Write (const void *buf, size_t num_bytes) +Error +PipePosix::Write(const void *buf, size_t num_bytes, size_t &bytes_written) { - if (WriteDescriptorIsValid()) + bytes_written = 0; + Error error; + + if (CanWrite()) { const int fd = GetWriteFileDescriptor(); - return write (fd, buf, num_bytes); + int result = write(fd, buf, num_bytes); + if (result >= 0) + bytes_written = result; + else + error.SetErrorToErrno(); } - return 0; // Return 0 since errno won't be set if we didn't call write + else + error.SetError(EINVAL, eErrorTypePOSIX); + + return error; } |