summaryrefslogtreecommitdiffstats
path: root/lldb/source/Host/posix/PipePosix.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2014-12-17 18:02:19 +0000
committerZachary Turner <zturner@google.com>2014-12-17 18:02:19 +0000
commit0b9d3eefdbf2c9bb50e139c5272b413e8227d842 (patch)
treefa6ac73e658e94d59432d15646ce1416662954f0 /lldb/source/Host/posix/PipePosix.cpp
parent06b2c54db9132bc7b6e599c2a3252ea7f2a8b33b (diff)
downloadbcm5719-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.cpp187
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;
}
OpenPOWER on IntegriCloud