diff options
| author | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
|---|---|---|
| committer | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
| commit | b9c1b51e45b845debb76d8658edabca70ca56079 (patch) | |
| tree | dfcb5a13ef2b014202340f47036da383eaee74aa /lldb/source/Host/posix | |
| parent | d5aa73376966339caad04013510626ec2e42c760 (diff) | |
| download | bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip | |
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
Diffstat (limited to 'lldb/source/Host/posix')
| -rw-r--r-- | lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp | 1316 | ||||
| -rw-r--r-- | lldb/source/Host/posix/DomainSocket.cpp | 141 | ||||
| -rw-r--r-- | lldb/source/Host/posix/FileSystem.cpp | 401 | ||||
| -rw-r--r-- | lldb/source/Host/posix/HostInfoPosix.cpp | 309 | ||||
| -rw-r--r-- | lldb/source/Host/posix/HostProcessPosix.cpp | 122 | ||||
| -rw-r--r-- | lldb/source/Host/posix/HostThreadPosix.cpp | 83 | ||||
| -rw-r--r-- | lldb/source/Host/posix/LockFilePosix.cpp | 69 | ||||
| -rw-r--r-- | lldb/source/Host/posix/MainLoopPosix.cpp | 286 | ||||
| -rw-r--r-- | lldb/source/Host/posix/PipePosix.cpp | 479 | ||||
| -rw-r--r-- | lldb/source/Host/posix/ProcessLauncherPosix.cpp | 21 |
10 files changed, 1474 insertions, 1753 deletions
diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index a6d0958c8c6..f6ec94dbd4a 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -17,16 +17,16 @@ #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" #include "lldb/Host/Config.h" #include "lldb/Host/IOObject.h" -#include "lldb/Host/SocketAddress.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/SocketAddress.h" #include "lldb/Host/StringConvert.h" #include "lldb/Utility/SelectHelper.h" // C Includes #include <errno.h> #include <fcntl.h> -#include <string.h> #include <stdlib.h> +#include <string.h> #include <sys/types.h> #ifndef LLDB_DISABLE_POSIX @@ -54,526 +54,491 @@ using namespace lldb; using namespace lldb_private; -const char* ConnectionFileDescriptor::LISTEN_SCHEME = "listen"; -const char* ConnectionFileDescriptor::ACCEPT_SCHEME = "accept"; -const char* ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept"; -const char* ConnectionFileDescriptor::CONNECT_SCHEME = "connect"; -const char* ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect"; -const char* ConnectionFileDescriptor::UDP_SCHEME = "udp"; -const char* ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect"; -const char* ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = "unix-abstract-connect"; -const char* ConnectionFileDescriptor::FD_SCHEME = "fd"; -const char* ConnectionFileDescriptor::FILE_SCHEME = "file"; +const char *ConnectionFileDescriptor::LISTEN_SCHEME = "listen"; +const char *ConnectionFileDescriptor::ACCEPT_SCHEME = "accept"; +const char *ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept"; +const char *ConnectionFileDescriptor::CONNECT_SCHEME = "connect"; +const char *ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect"; +const char *ConnectionFileDescriptor::UDP_SCHEME = "udp"; +const char *ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect"; +const char *ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = + "unix-abstract-connect"; +const char *ConnectionFileDescriptor::FD_SCHEME = "fd"; +const char *ConnectionFileDescriptor::FILE_SCHEME = "file"; namespace { -const char* -GetURLAddress(const char *url, const char *scheme) -{ - const auto prefix = std::string(scheme) + "://"; - if (strstr(url, prefix.c_str()) != url) - return nullptr; +const char *GetURLAddress(const char *url, const char *scheme) { + const auto prefix = std::string(scheme) + "://"; + if (strstr(url, prefix.c_str()) != url) + return nullptr; - return url + prefix.size(); + return url + prefix.size(); } - } ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) - : Connection(), - m_pipe(), - m_mutex(), - m_shutting_down(false), + : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), - m_child_processes_inherit(child_processes_inherit) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", static_cast<void *>(this)); + m_child_processes_inherit(child_processes_inherit) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | + LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", + static_cast<void *>(this)); } ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) - : Connection(), - m_pipe(), - m_mutex(), - m_shutting_down(false), - m_waiting_for_accept(false), - m_child_processes_inherit(false) -{ - m_write_sp.reset(new File(fd, owns_fd)); - m_read_sp.reset(new File(fd, false)); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", - static_cast<void *>(this), fd, owns_fd); - OpenCommandPipe(); + : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), + m_waiting_for_accept(false), m_child_processes_inherit(false) { + m_write_sp.reset(new File(fd, owns_fd)); + m_read_sp.reset(new File(fd, false)); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | + LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = " + "%i, owns_fd = %i)", + static_cast<void *>(this), fd, owns_fd); + OpenCommandPipe(); } ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket) - : Connection(), - m_pipe(), - m_mutex(), - m_shutting_down(false), - m_waiting_for_accept(false), - m_child_processes_inherit(false) -{ - InitializeSocket(socket); + : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), + m_waiting_for_accept(false), m_child_processes_inherit(false) { + InitializeSocket(socket); } -ConnectionFileDescriptor::~ConnectionFileDescriptor() -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast<void *>(this)); - Disconnect(NULL); - CloseCommandPipe(); +ConnectionFileDescriptor::~ConnectionFileDescriptor() { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | + LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", + static_cast<void *>(this)); + Disconnect(NULL); + CloseCommandPipe(); } -void -ConnectionFileDescriptor::OpenCommandPipe() -{ - CloseCommandPipe(); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - // Make the command file descriptor here: - Error result = m_pipe.CreateNew(m_child_processes_inherit); - if (!result.Success()) - { - if (log) - log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast<void *>(this), - result.AsCString()); - } - else - { - if (log) - log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast<void *>(this), - m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor()); - } -} +void ConnectionFileDescriptor::OpenCommandPipe() { + CloseCommandPipe(); -void -ConnectionFileDescriptor::CloseCommandPipe() -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + // Make the command file descriptor here: + Error result = m_pipe.CreateNew(m_child_processes_inherit); + if (!result.Success()) { if (log) - log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast<void *>(this)); - - m_pipe.Close(); + log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not " + "make pipe: %s", + static_cast<void *>(this), result.AsCString()); + } else { + if (log) + log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success " + "readfd=%d writefd=%d", + static_cast<void *>(this), m_pipe.GetReadFileDescriptor(), + m_pipe.GetWriteFileDescriptor()); + } } -bool -ConnectionFileDescriptor::IsConnected() const -{ - return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid()); -} +void ConnectionFileDescriptor::CloseCommandPipe() { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", + static_cast<void *>(this)); -ConnectionStatus -ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", static_cast<void *>(this), s); + m_pipe.Close(); +} - OpenCommandPipe(); +bool ConnectionFileDescriptor::IsConnected() const { + return (m_read_sp && m_read_sp->IsValid()) || + (m_write_sp && m_write_sp->IsValid()); +} - if (s && s[0]) - { - const char *addr = nullptr; - if ((addr = GetURLAddress(s, LISTEN_SCHEME))) - { - // listen://HOST:PORT - return SocketListenAndAccept(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, ACCEPT_SCHEME))) - { - // unix://SOCKNAME - return NamedSocketAccept(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME))) - { - // unix://SOCKNAME - return NamedSocketAccept(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, CONNECT_SCHEME))) - { - return ConnectTCP(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME))) - { - return ConnectTCP(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UDP_SCHEME))) - { - return ConnectUDP(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME))) - { - // unix-connect://SOCKNAME - return NamedSocketConnect(addr, error_ptr); - } - else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME))) - { - // unix-abstract-connect://SOCKNAME - return UnixAbstractSocketConnect(addr, error_ptr); - } +ConnectionStatus ConnectionFileDescriptor::Connect(const char *s, + Error *error_ptr) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", + static_cast<void *>(this), s); + + OpenCommandPipe(); + + if (s && s[0]) { + const char *addr = nullptr; + if ((addr = GetURLAddress(s, LISTEN_SCHEME))) { + // listen://HOST:PORT + return SocketListenAndAccept(addr, error_ptr); + } else if ((addr = GetURLAddress(s, ACCEPT_SCHEME))) { + // unix://SOCKNAME + return NamedSocketAccept(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME))) { + // unix://SOCKNAME + return NamedSocketAccept(addr, error_ptr); + } else if ((addr = GetURLAddress(s, CONNECT_SCHEME))) { + return ConnectTCP(addr, error_ptr); + } else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME))) { + return ConnectTCP(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UDP_SCHEME))) { + return ConnectUDP(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME))) { + // unix-connect://SOCKNAME + return NamedSocketConnect(addr, error_ptr); + } else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME))) { + // unix-abstract-connect://SOCKNAME + return UnixAbstractSocketConnect(addr, error_ptr); + } #ifndef LLDB_DISABLE_POSIX - else if ((addr = GetURLAddress(s, FD_SCHEME))) - { - // Just passing a native file descriptor within this current process - // that is already opened (possibly from a service or other source). - bool success = false; - int fd = StringConvert::ToSInt32(addr, -1, 0, &success); - - if (success) - { - // We have what looks to be a valid file descriptor, but we - // should make sure it is. We currently are doing this by trying to - // get the flags from the file descriptor and making sure it - // isn't a bad fd. - errno = 0; - int flags = ::fcntl(fd, F_GETFL, 0); - if (flags == -1 || errno == EBADF) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s); - m_read_sp.reset(); - m_write_sp.reset(); - return eConnectionStatusError; - } - else - { - // Don't take ownership of a file descriptor that gets passed - // to us since someone else opened the file descriptor and - // handed it to us. - // TODO: Since are using a URL to open connection we should - // eventually parse options using the web standard where we - // have "fd://123?opt1=value;opt2=value" and we can have an - // option be "owns=1" or "owns=0" or something like this to - // allow us to specify this. For now, we assume we must - // assume we don't own it. - - std::unique_ptr<TCPSocket> tcp_socket; - tcp_socket.reset(new TCPSocket(fd, false)); - // Try and get a socket option from this file descriptor to - // see if this is a socket and set m_is_socket accordingly. - int resuse; - bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); - if (is_socket) - { - m_read_sp = std::move(tcp_socket); - m_write_sp = m_read_sp; - } - else - { - m_read_sp.reset(new File(fd, false)); - m_write_sp.reset(new File(fd, false)); - } - m_uri.assign(addr); - return eConnectionStatusSuccess; - } - } - - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", s); - m_read_sp.reset(); - m_write_sp.reset(); - return eConnectionStatusError; - } - else if ((addr = GetURLAddress(s, FILE_SCHEME))) - { - // file:///PATH - const char *path = addr; - int fd = -1; - do - { - fd = ::open(path, O_RDWR); - } while (fd == -1 && errno == EINTR); - - if (fd == -1) - { - if (error_ptr) - error_ptr->SetErrorToErrno(); - return eConnectionStatusError; - } - - if (::isatty(fd)) - { - // Set up serial terminal emulation - struct termios options; - ::tcgetattr(fd, &options); - - // Set port speed to maximum - ::cfsetospeed(&options, B115200); - ::cfsetispeed(&options, B115200); - - // Raw input, disable echo and signals - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - - // Make sure only one character is needed to return from a read - options.c_cc[VMIN] = 1; - options.c_cc[VTIME] = 0; - - ::tcsetattr(fd, TCSANOW, &options); - } - - int flags = ::fcntl(fd, F_GETFL, 0); - if (flags >= 0) - { - if ((flags & O_NONBLOCK) == 0) - { - flags |= O_NONBLOCK; - ::fcntl(fd, F_SETFL, flags); - } - } - m_read_sp.reset(new File(fd, true)); + else if ((addr = GetURLAddress(s, FD_SCHEME))) { + // Just passing a native file descriptor within this current process + // that is already opened (possibly from a service or other source). + bool success = false; + int fd = StringConvert::ToSInt32(addr, -1, 0, &success); + + if (success) { + // We have what looks to be a valid file descriptor, but we + // should make sure it is. We currently are doing this by trying to + // get the flags from the file descriptor and making sure it + // isn't a bad fd. + errno = 0; + int flags = ::fcntl(fd, F_GETFL, 0); + if (flags == -1 || errno == EBADF) { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s); + m_read_sp.reset(); + m_write_sp.reset(); + return eConnectionStatusError; + } else { + // Don't take ownership of a file descriptor that gets passed + // to us since someone else opened the file descriptor and + // handed it to us. + // TODO: Since are using a URL to open connection we should + // eventually parse options using the web standard where we + // have "fd://123?opt1=value;opt2=value" and we can have an + // option be "owns=1" or "owns=0" or something like this to + // allow us to specify this. For now, we assume we must + // assume we don't own it. + + std::unique_ptr<TCPSocket> tcp_socket; + tcp_socket.reset(new TCPSocket(fd, false)); + // Try and get a socket option from this file descriptor to + // see if this is a socket and set m_is_socket accordingly. + int resuse; + bool is_socket = + !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); + if (is_socket) { + m_read_sp = std::move(tcp_socket); + m_write_sp = m_read_sp; + } else { + m_read_sp.reset(new File(fd, false)); m_write_sp.reset(new File(fd, false)); - return eConnectionStatusSuccess; + } + m_uri.assign(addr); + return eConnectionStatusSuccess; } -#endif + } + + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", + s); + m_read_sp.reset(); + m_write_sp.reset(); + return eConnectionStatusError; + } else if ((addr = GetURLAddress(s, FILE_SCHEME))) { + // file:///PATH + const char *path = addr; + int fd = -1; + do { + fd = ::open(path, O_RDWR); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) { if (error_ptr) - error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s); + error_ptr->SetErrorToErrno(); return eConnectionStatusError; - } - if (error_ptr) - error_ptr->SetErrorString("invalid connect arguments"); - return eConnectionStatusError; -} + } -bool -ConnectionFileDescriptor::InterruptRead() -{ - size_t bytes_written = 0; - Error result = m_pipe.Write("i", 1, bytes_written); - return result.Success(); -} + if (::isatty(fd)) { + // Set up serial terminal emulation + struct termios options; + ::tcgetattr(fd, &options); -ConnectionStatus -ConnectionFileDescriptor::Disconnect(Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect ()", static_cast<void *>(this)); + // Set port speed to maximum + ::cfsetospeed(&options, B115200); + ::cfsetispeed(&options, B115200); - ConnectionStatus status = eConnectionStatusSuccess; + // Raw input, disable echo and signals + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - if (!IsConnected()) - { - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast<void *>(this)); - return eConnectionStatusSuccess; - } + // Make sure only one character is needed to return from a read + options.c_cc[VMIN] = 1; + options.c_cc[VTIME] = 0; - if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) - static_cast<Socket &>(*m_read_sp).PreDisconnect(); + ::tcsetattr(fd, TCSANOW, &options); + } - // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely - // because somebody is doing a blocking read on our file descriptor. If that's the case, - // then send the "q" char to the command file channel so the read will wake up and the connection - // will then know to shut down. - - m_shutting_down = true; - - std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); - if (!locker.try_lock()) - { - if (m_pipe.CanWrite()) - { - size_t bytes_written = 0; - Error result = m_pipe.Write("q", 1, bytes_written); - if (log) - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, error = '%s'.", - static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), result.AsCString()); - } - else if (log) - { - log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", - static_cast<void *>(this)); + int flags = ::fcntl(fd, F_GETFL, 0); + if (flags >= 0) { + if ((flags & O_NONBLOCK) == 0) { + flags |= O_NONBLOCK; + ::fcntl(fd, F_SETFL, flags); } - locker.lock(); + } + m_read_sp.reset(new File(fd, true)); + m_write_sp.reset(new File(fd, false)); + return eConnectionStatusSuccess; } - - Error error = m_read_sp->Close(); - Error error2 = m_write_sp->Close(); - if (error.Fail() || error2.Fail()) - status = eConnectionStatusError; +#endif if (error_ptr) - *error_ptr = error.Fail() ? error : error2; - - // Close any pipes we were using for async interrupts - m_pipe.Close(); - - m_uri.clear(); - m_shutting_down = false; - return status; + error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", + s); + return eConnectionStatusError; + } + if (error_ptr) + error_ptr->SetErrorString("invalid connect arguments"); + return eConnectionStatusError; } -size_t -ConnectionFileDescriptor::Read(void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - - std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); - if (!locker.try_lock()) - { - if (log) - log->Printf("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", static_cast<void *>(this)); - if (error_ptr) - error_ptr->SetErrorString("failed to get the connection lock for read."); - - status = eConnectionStatusTimedOut; - return 0; - } - - if (m_shutting_down) - { - status = eConnectionStatusError; - return 0; - } +bool ConnectionFileDescriptor::InterruptRead() { + size_t bytes_written = 0; + Error result = m_pipe.Write("i", 1, bytes_written); + return result.Success(); +} - status = BytesAvailable(timeout_usec, error_ptr); - if (status != eConnectionStatusSuccess) - return 0; +ConnectionStatus ConnectionFileDescriptor::Disconnect(Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf("%p ConnectionFileDescriptor::Disconnect ()", + static_cast<void *>(this)); - Error error; - size_t bytes_read = dst_len; - error = m_read_sp->Read(dst, bytes_read); + ConnectionStatus status = eConnectionStatusSuccess; + if (!IsConnected()) { if (log) - { - log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", - static_cast<void *>(this), static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), static_cast<void *>(dst), - static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read), error.AsCString()); - } - - if (bytes_read == 0) - { - error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. - status = eConnectionStatusEndOfFile; - } - - if (error_ptr) - *error_ptr = error; - - if (error.Fail()) - { - uint32_t error_value = error.GetError(); - switch (error_value) - { - case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. - if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) - status = eConnectionStatusTimedOut; - else - status = eConnectionStatusSuccess; - return 0; - - case EFAULT: // Buf points outside the allocated address space. - case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. - case EINVAL: // The pointer associated with fildes was negative. - case EIO: // An I/O error occurred while reading from the file system. - // The process group is orphaned. - // The file is a regular file, nbyte is greater than 0, - // the starting position is before the end-of-file, and - // the starting position is greater than or equal to the - // offset maximum established for the open file - // descriptor associated with fildes. - case EISDIR: // An attempt is made to read a directory. - case ENOBUFS: // An attempt to allocate a memory buffer fails. - case ENOMEM: // Insufficient memory is available. - status = eConnectionStatusError; - break; // Break to close.... - - case ENOENT: // no such file or directory - case EBADF: // fildes is not a valid file or socket descriptor open for reading. - case ENXIO: // An action is requested of a device that does not exist.. - // A requested action cannot be performed by the device. - case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. - case ENOTCONN: // A read is attempted on an unconnected socket. - status = eConnectionStatusLostConnection; - break; // Break to close.... - - case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. - status = eConnectionStatusTimedOut; - return 0; - - default: - if (log) - log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", static_cast<void *>(this), - strerror(error_value)); - status = eConnectionStatusError; - break; // Break to close.... - } - - return 0; + log->Printf( + "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", + static_cast<void *>(this)); + return eConnectionStatusSuccess; + } + + if (m_read_sp && m_read_sp->IsValid() && + m_read_sp->GetFdType() == IOObject::eFDTypeSocket) + static_cast<Socket &>(*m_read_sp).PreDisconnect(); + + // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite + // likely + // because somebody is doing a blocking read on our file descriptor. If + // that's the case, + // then send the "q" char to the command file channel so the read will wake up + // and the connection + // will then know to shut down. + + m_shutting_down = true; + + std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); + if (!locker.try_lock()) { + if (m_pipe.CanWrite()) { + size_t bytes_written = 0; + Error result = m_pipe.Write("q", 1, bytes_written); + if (log) + log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get " + "the lock, sent 'q' to %d, error = '%s'.", + static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), + result.AsCString()); + } else if (log) { + log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the " + "lock, but no command pipe is available.", + static_cast<void *>(this)); } - return bytes_read; + locker.lock(); + } + + Error error = m_read_sp->Close(); + Error error2 = m_write_sp->Close(); + if (error.Fail() || error2.Fail()) + status = eConnectionStatusError; + if (error_ptr) + *error_ptr = error.Fail() ? error : error2; + + // Close any pipes we were using for async interrupts + m_pipe.Close(); + + m_uri.clear(); + m_shutting_down = false; + return status; } -size_t -ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", static_cast<void *>(this), - static_cast<const void *>(src), static_cast<uint64_t>(src_len)); - - if (!IsConnected()) - { - if (error_ptr) - error_ptr->SetErrorString("not connected"); - status = eConnectionStatusNoConnection; - return 0; - } - - Error error; - - size_t bytes_sent = src_len; - error = m_write_sp->Write(src, bytes_sent); +size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, + uint32_t timeout_usec, + ConnectionStatus &status, + Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); + if (!locker.try_lock()) { if (log) - { - log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", - static_cast<void *>(this), static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), static_cast<const void *>(src), - static_cast<uint64_t>(src_len), static_cast<uint64_t>(bytes_sent), error.AsCString()); - } - + log->Printf("%p ConnectionFileDescriptor::Read () failed to get the " + "connection lock.", + static_cast<void *>(this)); if (error_ptr) - *error_ptr = error; + error_ptr->SetErrorString("failed to get the connection lock for read."); + + status = eConnectionStatusTimedOut; + return 0; + } + + if (m_shutting_down) { + status = eConnectionStatusError; + return 0; + } + + status = BytesAvailable(timeout_usec, error_ptr); + if (status != eConnectionStatusSuccess) + return 0; + + Error error; + size_t bytes_read = dst_len; + error = m_read_sp->Read(dst, bytes_read); + + if (log) { + log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 + ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", + static_cast<void *>(this), + static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), + static_cast<void *>(dst), static_cast<uint64_t>(dst_len), + static_cast<uint64_t>(bytes_read), error.AsCString()); + } + + if (bytes_read == 0) { + error.Clear(); // End-of-file. Do not automatically close; pass along for + // the end-of-file handlers. + status = eConnectionStatusEndOfFile; + } + + if (error_ptr) + *error_ptr = error; + + if (error.Fail()) { + uint32_t error_value = error.GetError(); + switch (error_value) { + case EAGAIN: // The file was marked for non-blocking I/O, and no data were + // ready to be read. + if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) + status = eConnectionStatusTimedOut; + else + status = eConnectionStatusSuccess; + return 0; + + case EFAULT: // Buf points outside the allocated address space. + case EINTR: // A read from a slow device was interrupted before any data + // arrived by the delivery of a signal. + case EINVAL: // The pointer associated with fildes was negative. + case EIO: // An I/O error occurred while reading from the file system. + // The process group is orphaned. + // The file is a regular file, nbyte is greater than 0, + // the starting position is before the end-of-file, and + // the starting position is greater than or equal to the + // offset maximum established for the open file + // descriptor associated with fildes. + case EISDIR: // An attempt is made to read a directory. + case ENOBUFS: // An attempt to allocate a memory buffer fails. + case ENOMEM: // Insufficient memory is available. + status = eConnectionStatusError; + break; // Break to close.... + + case ENOENT: // no such file or directory + case EBADF: // fildes is not a valid file or socket descriptor open for + // reading. + case ENXIO: // An action is requested of a device that does not exist.. + // A requested action cannot be performed by the device. + case ECONNRESET: // The connection is closed by the peer during a read + // attempt on a socket. + case ENOTCONN: // A read is attempted on an unconnected socket. + status = eConnectionStatusLostConnection; + break; // Break to close.... + + case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a + // socket. + status = eConnectionStatusTimedOut; + return 0; + + default: + if (log) + log->Printf( + "%p ConnectionFileDescriptor::Read (), unexpected error: %s", + static_cast<void *>(this), strerror(error_value)); + status = eConnectionStatusError; + break; // Break to close.... + } - if (error.Fail()) - { - switch (error.GetError()) - { - case EAGAIN: - case EINTR: - status = eConnectionStatusSuccess; - return 0; - - case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. - case ENOTCONN: // A read is attempted on an unconnected socket. - status = eConnectionStatusLostConnection; - break; // Break to close.... - - default: - status = eConnectionStatusError; - break; // Break to close.... - } + return 0; + } + return bytes_read; +} - return 0; +size_t ConnectionFileDescriptor::Write(const void *src, size_t src_len, + ConnectionStatus &status, + Error *error_ptr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf( + "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", + static_cast<void *>(this), static_cast<const void *>(src), + static_cast<uint64_t>(src_len)); + + if (!IsConnected()) { + if (error_ptr) + error_ptr->SetErrorString("not connected"); + status = eConnectionStatusNoConnection; + return 0; + } + + Error error; + + size_t bytes_sent = src_len; + error = m_write_sp->Write(src, bytes_sent); + + if (log) { + log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 + ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 + " (error = %s)", + static_cast<void *>(this), + static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), + static_cast<const void *>(src), static_cast<uint64_t>(src_len), + static_cast<uint64_t>(bytes_sent), error.AsCString()); + } + + if (error_ptr) + *error_ptr = error; + + if (error.Fail()) { + switch (error.GetError()) { + case EAGAIN: + case EINTR: + status = eConnectionStatusSuccess; + return 0; + + case ECONNRESET: // The connection is closed by the peer during a read + // attempt on a socket. + case ENOTCONN: // A read is attempted on an unconnected socket. + status = eConnectionStatusLostConnection; + break; // Break to close.... + + default: + status = eConnectionStatusError; + break; // Break to close.... } - status = eConnectionStatusSuccess; - return bytes_sent; -} + return 0; + } -std::string -ConnectionFileDescriptor::GetURI() -{ - return m_uri; + status = eConnectionStatusSuccess; + return bytes_sent; } -// This ConnectionFileDescriptor::BytesAvailable() uses select() via SelectHelper +std::string ConnectionFileDescriptor::GetURI() { return m_uri; } + +// This ConnectionFileDescriptor::BytesAvailable() uses select() via +// SelectHelper // // PROS: // - select is consistent across most unix platforms @@ -587,260 +552,247 @@ ConnectionFileDescriptor::GetURI() // be used or a new version of ConnectionFileDescriptor::BytesAvailable() // should be written for the system that is running into the limitations. +ConnectionStatus ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, + Error *error_ptr) { + // Don't need to take the mutex here separately since we are only called from + // Read. If we + // ever get used more generally we will need to lock here as well. + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf( + "%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", + static_cast<void *>(this), timeout_usec); + + // Make a copy of the file descriptors to make sure we don't + // have another thread change these values out from under us + // and cause problems in the loop below where like in FS_SET() + const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); + const int pipe_fd = m_pipe.GetReadFileDescriptor(); + + if (handle != IOObject::kInvalidHandleValue) { + SelectHelper select_helper; + if (timeout_usec != UINT32_MAX) + select_helper.SetTimeout(std::chrono::microseconds(timeout_usec)); + + select_helper.FDSetRead(handle); +#if defined(_MSC_VER) + // select() won't accept pipes on Windows. The entire Windows codepath + // needs to be + // converted over to using WaitForMultipleObjects and event HANDLEs, but for + // now at least + // this will allow ::select() to not return an error. + const bool have_pipe_fd = false; +#else + const bool have_pipe_fd = pipe_fd >= 0; +#endif + if (have_pipe_fd) + select_helper.FDSetRead(pipe_fd); -ConnectionStatus -ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr) -{ - // Don't need to take the mutex here separately since we are only called from Read. If we - // ever get used more generally we will need to lock here as well. + while (handle == m_read_sp->GetWaitableHandle()) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); - if (log) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", static_cast<void *>(this), timeout_usec); + Error error = select_helper.Select(); + if (error_ptr) + *error_ptr = error; - // Make a copy of the file descriptors to make sure we don't - // have another thread change these values out from under us - // and cause problems in the loop below where like in FS_SET() - const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); - const int pipe_fd = m_pipe.GetReadFileDescriptor(); + if (error.Fail()) { + switch (error.GetError()) { + case EBADF: // One of the descriptor sets specified an invalid + // descriptor. + return eConnectionStatusLostConnection; + + case EINVAL: // The specified time limit is invalid. One of its + // components is negative or too large. + default: // Other unknown error + return eConnectionStatusError; + + case ETIMEDOUT: + return eConnectionStatusTimedOut; + + case EAGAIN: // The kernel was (perhaps temporarily) unable to + // allocate the requested number of file descriptors, + // or we have non-blocking IO + case EINTR: // A signal was delivered before the time limit + // expired and before any of the selected events + // occurred. + break; // Lets keep reading to until we timeout + } + } else { + if (select_helper.FDIsSetRead(handle)) + return eConnectionStatusSuccess; + if (select_helper.FDIsSetRead(pipe_fd)) { + // There is an interrupt or exit command in the command pipe + // Read the data from that pipe: + char buffer[1]; - if (handle != IOObject::kInvalidHandleValue) - { - SelectHelper select_helper; - if (timeout_usec != UINT32_MAX) - select_helper.SetTimeout(std::chrono::microseconds(timeout_usec)); + ssize_t bytes_read; - select_helper.FDSetRead(handle); -#if defined(_MSC_VER) - // select() won't accept pipes on Windows. The entire Windows codepath needs to be - // converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least - // this will allow ::select() to not return an error. - const bool have_pipe_fd = false; -#else - const bool have_pipe_fd = pipe_fd >= 0; -#endif - if (have_pipe_fd) - select_helper.FDSetRead(pipe_fd); - - while (handle == m_read_sp->GetWaitableHandle()) - { - - Error error = select_helper.Select(); - - if (error_ptr) - *error_ptr = error; - - if (error.Fail()) - { - switch (error.GetError()) - { - case EBADF: // One of the descriptor sets specified an invalid descriptor. - return eConnectionStatusLostConnection; - - case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. - default: // Other unknown error - return eConnectionStatusError; - - case ETIMEDOUT: - return eConnectionStatusTimedOut; - - case EAGAIN: // The kernel was (perhaps temporarily) unable to - // allocate the requested number of file descriptors, - // or we have non-blocking IO - case EINTR: // A signal was delivered before the time limit - // expired and before any of the selected events - // occurred. - break; // Lets keep reading to until we timeout - } - } - else - { - if (select_helper.FDIsSetRead(handle)) - return eConnectionStatusSuccess; - - if (select_helper.FDIsSetRead(pipe_fd)) - { - // There is an interrupt or exit command in the command pipe - // Read the data from that pipe: - char buffer[1]; - - ssize_t bytes_read; - - do - { - bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); - } while (bytes_read < 0 && errno == EINTR); - - switch (buffer[0]) - { - case 'q': - if (log) - log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " - "got data: %c from the command channel.", - static_cast<void *>(this), buffer[0]); - return eConnectionStatusEndOfFile; - case 'i': - // Interrupt the current read - return eConnectionStatusInterrupted; - } - } - } + do { + bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); + } while (bytes_read < 0 && errno == EINTR); + + switch (buffer[0]) { + case 'q': + if (log) + log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " + "got data: %c from the command channel.", + static_cast<void *>(this), buffer[0]); + return eConnectionStatusEndOfFile; + case 'i': + // Interrupt the current read + return eConnectionStatusInterrupted; + } } + } } + } - if (error_ptr) - error_ptr->SetErrorString("not connected"); - return eConnectionStatusLostConnection; + if (error_ptr) + error_ptr->SetErrorString("not connected"); + return eConnectionStatusLostConnection; } ConnectionStatus -ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(socket_name); - return eConnectionStatusSuccess; +ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = + Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus -ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(socket_name); - return eConnectionStatusSuccess; +ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = + Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } lldb::ConnectionStatus -ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(socket_name); - return eConnectionStatusSuccess; +ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = Socket::UnixAbstractConnect(socket_name, + m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus -ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) -{ - m_port_predicate.SetValue(0, eBroadcastNever); - - Socket *socket = nullptr; - m_waiting_for_accept = true; - Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate); - if (error_ptr) - *error_ptr = error; - if (error.Fail()) - return eConnectionStatusError; +ConnectionFileDescriptor::SocketListenAndAccept(const char *s, + Error *error_ptr) { + m_port_predicate.SetValue(0, eBroadcastNever); + + Socket *socket = nullptr; + m_waiting_for_accept = true; + Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, + &m_port_predicate); + if (error_ptr) + *error_ptr = error; + if (error.Fail()) + return eConnectionStatusError; - std::unique_ptr<Socket> listening_socket_up; + std::unique_ptr<Socket> listening_socket_up; - listening_socket_up.reset(socket); - socket = nullptr; - error = listening_socket_up->Accept(s, m_child_processes_inherit, socket); - listening_socket_up.reset(); - if (error_ptr) - *error_ptr = error; - if (error.Fail()) - return eConnectionStatusError; + listening_socket_up.reset(socket); + socket = nullptr; + error = listening_socket_up->Accept(s, m_child_processes_inherit, socket); + listening_socket_up.reset(); + if (error_ptr) + *error_ptr = error; + if (error.Fail()) + return eConnectionStatusError; - InitializeSocket(socket); - return eConnectionStatusSuccess; + InitializeSocket(socket); + return eConnectionStatusSuccess; } -ConnectionStatus -ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) -{ - Socket *socket = nullptr; - Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(s); - return eConnectionStatusSuccess; +ConnectionStatus ConnectionFileDescriptor::ConnectTCP(const char *s, + Error *error_ptr) { + Socket *socket = nullptr; + Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(s); + return eConnectionStatusSuccess; } -ConnectionStatus -ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) -{ - Socket *send_socket = nullptr; - Socket *recv_socket = nullptr; - Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, recv_socket); - if (error_ptr) - *error_ptr = error; - m_write_sp.reset(send_socket); - m_read_sp.reset(recv_socket); - if (error.Fail()) - { - return eConnectionStatusError; - } - m_uri.assign(s); - return eConnectionStatusSuccess; +ConnectionStatus ConnectionFileDescriptor::ConnectUDP(const char *s, + Error *error_ptr) { + Socket *send_socket = nullptr; + Socket *recv_socket = nullptr; + Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, + recv_socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(send_socket); + m_read_sp.reset(recv_socket); + if (error.Fail()) { + return eConnectionStatusError; + } + m_uri.assign(s); + return eConnectionStatusSuccess; } -uint16_t -ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) -{ - uint16_t bound_port = 0; - if (timeout_sec == UINT32_MAX) - m_port_predicate.WaitForValueNotEqualTo(0, bound_port); - else - m_port_predicate.WaitForValueNotEqualTo(0, bound_port, std::chrono::seconds(timeout_sec)); - return bound_port; +uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) { + uint16_t bound_port = 0; + if (timeout_sec == UINT32_MAX) + m_port_predicate.WaitForValueNotEqualTo(0, bound_port); + else + m_port_predicate.WaitForValueNotEqualTo(0, bound_port, + std::chrono::seconds(timeout_sec)); + return bound_port; } -bool -ConnectionFileDescriptor::GetChildProcessesInherit() const -{ - return m_child_processes_inherit; +bool ConnectionFileDescriptor::GetChildProcessesInherit() const { + return m_child_processes_inherit; } -void -ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit) -{ - m_child_processes_inherit = child_processes_inherit; +void ConnectionFileDescriptor::SetChildProcessesInherit( + bool child_processes_inherit) { + m_child_processes_inherit = child_processes_inherit; } -void -ConnectionFileDescriptor::InitializeSocket(Socket* socket) -{ - assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); - TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket); - - m_write_sp.reset(socket); - m_read_sp = m_write_sp; - StreamString strm; - strm.Printf("connect://%s:%u",tcp_socket->GetRemoteIPAddress().c_str(), tcp_socket->GetRemotePortNumber()); - m_uri.swap(strm.GetString()); +void ConnectionFileDescriptor::InitializeSocket(Socket *socket) { + assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); + TCPSocket *tcp_socket = static_cast<TCPSocket *>(socket); + + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + StreamString strm; + strm.Printf("connect://%s:%u", tcp_socket->GetRemoteIPAddress().c_str(), + tcp_socket->GetRemotePortNumber()); + m_uri.swap(strm.GetString()); } diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 9dc147196c0..cb0a1d05750 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -21,113 +21,100 @@ using namespace lldb_private; #ifdef __ANDROID__ // Android does not have SUN_LEN #ifndef SUN_LEN -#define SUN_LEN(ptr) (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path)) +#define SUN_LEN(ptr) \ + (offsetof(struct sockaddr_un, sun_path) + strlen((ptr)->sun_path)) #endif #endif // #ifdef __ANDROID__ namespace { const int kDomain = AF_UNIX; -const int kType = SOCK_STREAM; +const int kType = SOCK_STREAM; -bool SetSockAddr(llvm::StringRef name, - const size_t name_offset, - sockaddr_un* saddr_un, - socklen_t& saddr_un_len) -{ - if (name.size() + name_offset > sizeof(saddr_un->sun_path)) - return false; +bool SetSockAddr(llvm::StringRef name, const size_t name_offset, + sockaddr_un *saddr_un, socklen_t &saddr_un_len) { + if (name.size() + name_offset > sizeof(saddr_un->sun_path)) + return false; - memset(saddr_un, 0, sizeof(*saddr_un)); - saddr_un->sun_family = kDomain; + memset(saddr_un, 0, sizeof(*saddr_un)); + saddr_un->sun_family = kDomain; - memcpy(saddr_un->sun_path + name_offset, name.data(), name.size()); + memcpy(saddr_un->sun_path + name_offset, name.data(), name.size()); - // For domain sockets we can use SUN_LEN in order to calculate size of - // sockaddr_un, but for abstract sockets we have to calculate size manually - // because of leading null symbol. - if (name_offset == 0) - saddr_un_len = SUN_LEN(saddr_un); - else - saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); + // For domain sockets we can use SUN_LEN in order to calculate size of + // sockaddr_un, but for abstract sockets we have to calculate size manually + // because of leading null symbol. + if (name_offset == 0) + saddr_un_len = SUN_LEN(saddr_un); + else + saddr_un_len = + offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un->sun_len = saddr_un_len; + saddr_un->sun_len = saddr_un_len; #endif - return true; + return true; } - } DomainSocket::DomainSocket(NativeSocket socket) - : Socket(socket, ProtocolUnixDomain, true) -{ -} + : Socket(socket, ProtocolUnixDomain, true) {} DomainSocket::DomainSocket(bool child_processes_inherit, Error &error) - : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) -{ -} - -DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error) - : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true) -{ -} - -Error -DomainSocket::Connect(llvm::StringRef name) -{ - sockaddr_un saddr_un; - socklen_t saddr_un_len; - if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) - return Error("Failed to set socket address"); - - Error error; - if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < 0) - SetLastError (error); + : DomainSocket( + CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} + +DomainSocket::DomainSocket(SocketProtocol protocol, + bool child_processes_inherit, Error &error) + : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), + protocol, true) {} + +Error DomainSocket::Connect(llvm::StringRef name) { + sockaddr_un saddr_un; + socklen_t saddr_un_len; + if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) + return Error("Failed to set socket address"); + + Error error; + if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < + 0) + SetLastError(error); - return error; + return error; } -Error -DomainSocket::Listen(llvm::StringRef name, int backlog) -{ - sockaddr_un saddr_un; - socklen_t saddr_un_len; - if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) - return Error("Failed to set socket address"); +Error DomainSocket::Listen(llvm::StringRef name, int backlog) { + sockaddr_un saddr_un; + socklen_t saddr_un_len; + if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) + return Error("Failed to set socket address"); - DeleteSocketFile(name); + DeleteSocketFile(name); - Error error; - if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == 0) - if (::listen(GetNativeSocket(), backlog) == 0) - return error; + Error error; + if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == + 0) + if (::listen(GetNativeSocket(), backlog) == 0) + return error; - SetLastError(error); - return error; + SetLastError(error); + return error; } -Error -DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) -{ - Error error; - auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error); - if (error.Success()) - socket = new DomainSocket(conn_fd); +Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, + Socket *&socket) { + Error error; + auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, + child_processes_inherit, error); + if (error.Success()) + socket = new DomainSocket(conn_fd); - return error; + return error; } -size_t -DomainSocket::GetNameOffset() const -{ - return 0; -} +size_t DomainSocket::GetNameOffset() const { return 0; } -void -DomainSocket::DeleteSocketFile(llvm::StringRef name) -{ - FileSystem::Unlink(FileSpec{name, true}); +void DomainSocket::DeleteSocketFile(llvm::StringRef name) { + FileSystem::Unlink(FileSpec{name, true}); } diff --git a/lldb/source/Host/posix/FileSystem.cpp b/lldb/source/Host/posix/FileSystem.cpp index c8fa1bc9cf4..aaa53ce0772 100644 --- a/lldb/source/Host/posix/FileSystem.cpp +++ b/lldb/source/Host/posix/FileSystem.cpp @@ -16,9 +16,9 @@ #include <sys/stat.h> #include <sys/types.h> #ifdef __linux__ -#include <sys/statfs.h> -#include <sys/mount.h> #include <linux/magic.h> +#include <sys/mount.h> +#include <sys/statfs.h> #endif #if defined(__NetBSD__) #include <sys/statvfs.h> @@ -32,282 +32,231 @@ using namespace lldb; using namespace lldb_private; -const char * -FileSystem::DEV_NULL = "/dev/null"; +const char *FileSystem::DEV_NULL = "/dev/null"; -FileSpec::PathSyntax -FileSystem::GetNativePathSyntax() -{ - return FileSpec::ePathSyntaxPosix; +FileSpec::PathSyntax FileSystem::GetNativePathSyntax() { + return FileSpec::ePathSyntaxPosix; } -Error -FileSystem::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions) -{ - if (file_spec) - { - Error error; - if (::mkdir(file_spec.GetCString(), file_permissions) == -1) - { - error.SetErrorToErrno(); - errno = 0; - switch (error.GetError()) - { - case ENOENT: - { - // Parent directory doesn't exist, so lets make it if we can - // Make the parent directory and try again - FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false}; - error = MakeDirectory(parent_file_spec, file_permissions); - if (error.Fail()) - return error; - // Try and make the directory again now that the parent directory was made successfully - if (::mkdir(file_spec.GetCString(), file_permissions) == -1) - { - error.SetErrorToErrno(); - } - return error; - } - break; - case EEXIST: - { - if (file_spec.IsDirectory()) - return Error(); // It is a directory and it already exists - } - break; - } +Error FileSystem::MakeDirectory(const FileSpec &file_spec, + uint32_t file_permissions) { + if (file_spec) { + Error error; + if (::mkdir(file_spec.GetCString(), file_permissions) == -1) { + error.SetErrorToErrno(); + errno = 0; + switch (error.GetError()) { + case ENOENT: { + // Parent directory doesn't exist, so lets make it if we can + // Make the parent directory and try again + FileSpec parent_file_spec{file_spec.GetDirectory().GetCString(), false}; + error = MakeDirectory(parent_file_spec, file_permissions); + if (error.Fail()) + return error; + // Try and make the directory again now that the parent directory was + // made successfully + if (::mkdir(file_spec.GetCString(), file_permissions) == -1) { + error.SetErrorToErrno(); } return error; + } break; + case EEXIST: { + if (file_spec.IsDirectory()) + return Error(); // It is a directory and it already exists + } break; + } } - return Error("empty path"); + return error; + } + return Error("empty path"); } -Error -FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) -{ - Error error; - if (file_spec) - { - if (recurse) - { - // Save all sub directories in a list so we don't recursively call this function - // and possibly run out of file descriptors if the directory is too deep. - std::vector<FileSpec> sub_directories; - - FileSpec::ForEachItemInDirectory (file_spec.GetCString(), [&error, &sub_directories](FileSpec::FileType file_type, const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult { - if (file_type == FileSpec::eFileTypeDirectory) - { - // Save all directorires and process them after iterating through this directory - sub_directories.push_back(spec); - } - else - { - // Update sub_spec to point to the current file and delete it - error = FileSystem::Unlink(spec); - } - // If anything went wrong, stop iterating, else process the next file - if (error.Fail()) - return FileSpec::eEnumerateDirectoryResultQuit; - else - return FileSpec::eEnumerateDirectoryResultNext; - }); +Error FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse) { + Error error; + if (file_spec) { + if (recurse) { + // Save all sub directories in a list so we don't recursively call this + // function + // and possibly run out of file descriptors if the directory is too deep. + std::vector<FileSpec> sub_directories; - if (error.Success()) - { - // Now delete all sub directories with separate calls that aren't - // recursively calling into this function _while_ this function is - // iterating through the current directory. - for (const auto &sub_directory : sub_directories) - { - error = DeleteDirectory(sub_directory, recurse); - if (error.Fail()) - break; - } + FileSpec::ForEachItemInDirectory( + file_spec.GetCString(), + [&error, &sub_directories]( + FileSpec::FileType file_type, + const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult { + if (file_type == FileSpec::eFileTypeDirectory) { + // Save all directorires and process them after iterating through + // this directory + sub_directories.push_back(spec); + } else { + // Update sub_spec to point to the current file and delete it + error = FileSystem::Unlink(spec); } - } + // If anything went wrong, stop iterating, else process the next + // file + if (error.Fail()) + return FileSpec::eEnumerateDirectoryResultQuit; + else + return FileSpec::eEnumerateDirectoryResultNext; + }); - if (error.Success()) - { - if (::rmdir(file_spec.GetCString()) != 0) - error.SetErrorToErrno(); + if (error.Success()) { + // Now delete all sub directories with separate calls that aren't + // recursively calling into this function _while_ this function is + // iterating through the current directory. + for (const auto &sub_directory : sub_directories) { + error = DeleteDirectory(sub_directory, recurse); + if (error.Fail()) + break; } + } } - else - { - error.SetErrorString("empty path"); - } - return error; -} -Error -FileSystem::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) -{ - Error error; - struct stat file_stats; - if (::stat(file_spec.GetCString(), &file_stats) == 0) - { - // The bits in "st_mode" currently match the definitions - // for the file mode bits in unix. - file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - else - { + if (error.Success()) { + if (::rmdir(file_spec.GetCString()) != 0) error.SetErrorToErrno(); } - return error; + } else { + error.SetErrorString("empty path"); + } + return error; } -Error -FileSystem::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) -{ - Error error; - if (::chmod(file_spec.GetCString(), file_permissions) != 0) - error.SetErrorToErrno(); - return error; +Error FileSystem::GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions) { + Error error; + struct stat file_stats; + if (::stat(file_spec.GetCString(), &file_stats) == 0) { + // The bits in "st_mode" currently match the definitions + // for the file mode bits in unix. + file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } else { + error.SetErrorToErrno(); + } + return error; } -lldb::user_id_t -FileSystem::GetFileSize(const FileSpec &file_spec) -{ - return file_spec.GetByteSize(); +Error FileSystem::SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions) { + Error error; + if (::chmod(file_spec.GetCString(), file_permissions) != 0) + error.SetErrorToErrno(); + return error; } -bool -FileSystem::GetFileExists(const FileSpec &file_spec) -{ - return file_spec.Exists(); +lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) { + return file_spec.GetByteSize(); } -Error -FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - if (::link(dst.GetCString(), src.GetCString()) == -1) - error.SetErrorToErrno(); - return error; +bool FileSystem::GetFileExists(const FileSpec &file_spec) { + return file_spec.Exists(); } -int -FileSystem::GetHardlinkCount(const FileSpec &file_spec) -{ - struct stat file_stat; - if (::stat(file_spec.GetCString(), &file_stat) == 0) - return file_stat.st_nlink; +Error FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) { + Error error; + if (::link(dst.GetCString(), src.GetCString()) == -1) + error.SetErrorToErrno(); + return error; +} + +int FileSystem::GetHardlinkCount(const FileSpec &file_spec) { + struct stat file_stat; + if (::stat(file_spec.GetCString(), &file_stat) == 0) + return file_stat.st_nlink; - return -1; + return -1; } -Error -FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) -{ - Error error; - if (::symlink(dst.GetCString(), src.GetCString()) == -1) - error.SetErrorToErrno(); - return error; +Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { + Error error; + if (::symlink(dst.GetCString(), src.GetCString()) == -1) + error.SetErrorToErrno(); + return error; } -Error -FileSystem::Unlink(const FileSpec &file_spec) -{ - Error error; - if (::unlink(file_spec.GetCString()) == -1) - error.SetErrorToErrno(); - return error; +Error FileSystem::Unlink(const FileSpec &file_spec) { + Error error; + if (::unlink(file_spec.GetCString()) == -1) + error.SetErrorToErrno(); + return error; } -Error -FileSystem::Readlink(const FileSpec &src, FileSpec &dst) -{ - Error error; - char buf[PATH_MAX]; - ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1); - if (count < 0) - error.SetErrorToErrno(); - else - { - buf[count] = '\0'; // Success - dst.SetFile(buf, false); - } - return error; +Error FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { + Error error; + char buf[PATH_MAX]; + ssize_t count = ::readlink(src.GetCString(), buf, sizeof(buf) - 1); + if (count < 0) + error.SetErrorToErrno(); + else { + buf[count] = '\0'; // Success + dst.SetFile(buf, false); + } + return error; } -Error -FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) -{ - char resolved_path[PATH_MAX]; - if (!src.GetPath (resolved_path, sizeof (resolved_path))) - { - return Error("Couldn't get the canonical path for %s", src.GetCString()); - } - - char real_path[PATH_MAX + 1]; - if (realpath(resolved_path, real_path) == nullptr) - { - Error err; - err.SetErrorToErrno(); - return err; - } - - dst = FileSpec(real_path, false); - - return Error(); +Error FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) { + char resolved_path[PATH_MAX]; + if (!src.GetPath(resolved_path, sizeof(resolved_path))) { + return Error("Couldn't get the canonical path for %s", src.GetCString()); + } + + char real_path[PATH_MAX + 1]; + if (realpath(resolved_path, real_path) == nullptr) { + Error err; + err.SetErrorToErrno(); + return err; + } + + dst = FileSpec(real_path, false); + + return Error(); } #if defined(__NetBSD__) -static bool IsLocal(const struct statvfs& info) -{ - return (info.f_flag & MNT_LOCAL) != 0; +static bool IsLocal(const struct statvfs &info) { + return (info.f_flag & MNT_LOCAL) != 0; } #else -static bool IsLocal(const struct statfs& info) -{ +static bool IsLocal(const struct statfs &info) { #ifdef __linux__ - #define CIFS_MAGIC_NUMBER 0xFF534D42 - switch ((uint32_t)info.f_type) - { - case NFS_SUPER_MAGIC: - case SMB_SUPER_MAGIC: - case CIFS_MAGIC_NUMBER: - return false; - default: - return true; - } +#define CIFS_MAGIC_NUMBER 0xFF534D42 + switch ((uint32_t)info.f_type) { + case NFS_SUPER_MAGIC: + case SMB_SUPER_MAGIC: + case CIFS_MAGIC_NUMBER: + return false; + default: + return true; + } #else - return (info.f_flags & MNT_LOCAL) != 0; + return (info.f_flags & MNT_LOCAL) != 0; #endif } #endif #if defined(__NetBSD__) -bool -FileSystem::IsLocal(const FileSpec &spec) -{ - struct statvfs statfs_info; - std::string path (spec.GetPath()); - if (statvfs(path.c_str(), &statfs_info) == 0) - return ::IsLocal(statfs_info); - return false; +bool FileSystem::IsLocal(const FileSpec &spec) { + struct statvfs statfs_info; + std::string path(spec.GetPath()); + if (statvfs(path.c_str(), &statfs_info) == 0) + return ::IsLocal(statfs_info); + return false; } #else -bool -FileSystem::IsLocal(const FileSpec &spec) -{ - struct statfs statfs_info; - std::string path (spec.GetPath()); - if (statfs(path.c_str(), &statfs_info) == 0) - return ::IsLocal(statfs_info); - return false; +bool FileSystem::IsLocal(const FileSpec &spec) { + struct statfs statfs_info; + std::string path(spec.GetPath()); + if (statfs(path.c_str(), &statfs_info) == 0) + return ::IsLocal(statfs_info); + return false; } #endif -FILE * -FileSystem::Fopen(const char *path, const char *mode) -{ - return ::fopen(path, mode); +FILE *FileSystem::Fopen(const char *path, const char *mode) { + return ::fopen(path, mode); } -int -FileSystem::Stat(const char *path, struct stat *stats) -{ - return ::stat(path, stats); +int FileSystem::Stat(const char *path, struct stat *stats) { + return ::stat(path, stats); } diff --git a/lldb/source/Host/posix/HostInfoPosix.cpp b/lldb/source/Host/posix/HostInfoPosix.cpp index d0ef2ca3706..9ff96625cdb 100644 --- a/lldb/source/Host/posix/HostInfoPosix.cpp +++ b/lldb/source/Host/posix/HostInfoPosix.cpp @@ -28,27 +28,20 @@ using namespace lldb_private; -size_t -HostInfoPosix::GetPageSize() -{ - return ::getpagesize(); -} - -bool -HostInfoPosix::GetHostname(std::string &s) -{ - char hostname[PATH_MAX]; - hostname[sizeof(hostname) - 1] = '\0'; - if (::gethostname(hostname, sizeof(hostname) - 1) == 0) - { - struct hostent *h = ::gethostbyname(hostname); - if (h) - s.assign(h->h_name); - else - s.assign(hostname); - return true; - } - return false; +size_t HostInfoPosix::GetPageSize() { return ::getpagesize(); } + +bool HostInfoPosix::GetHostname(std::string &s) { + char hostname[PATH_MAX]; + hostname[sizeof(hostname) - 1] = '\0'; + if (::gethostname(hostname, sizeof(hostname) - 1) == 0) { + struct hostent *h = ::gethostbyname(hostname); + if (h) + s.assign(h->h_name); + else + s.assign(hostname); + return true; + } + return false; } #ifdef __ANDROID_NDK__ @@ -62,194 +55,164 @@ HostInfoPosix::GetHostname(std::string &s) static std::mutex s_getpwuid_lock; #endif -const char * -HostInfoPosix::LookupUserName(uint32_t uid, std::string &user_name) -{ +const char *HostInfoPosix::LookupUserName(uint32_t uid, + std::string &user_name) { #ifdef USE_GETPWUID - // getpwuid_r is missing from android-9 - // make getpwuid thread safe with a mutex - std::lock_guard<std::mutex> lock(s_getpwuid_lock); - struct passwd *user_info_ptr = ::getpwuid(uid); - if (user_info_ptr) - { - user_name.assign(user_info_ptr->pw_name); - return user_name.c_str(); - } + // getpwuid_r is missing from android-9 + // make getpwuid thread safe with a mutex + std::lock_guard<std::mutex> lock(s_getpwuid_lock); + struct passwd *user_info_ptr = ::getpwuid(uid); + if (user_info_ptr) { + user_name.assign(user_info_ptr->pw_name); + return user_name.c_str(); + } #else - struct passwd user_info; - struct passwd *user_info_ptr = &user_info; - char user_buffer[PATH_MAX]; - size_t user_buffer_size = sizeof(user_buffer); - if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, &user_info_ptr) == 0) - { - if (user_info_ptr) - { - user_name.assign(user_info_ptr->pw_name); - return user_name.c_str(); - } + struct passwd user_info; + struct passwd *user_info_ptr = &user_info; + char user_buffer[PATH_MAX]; + size_t user_buffer_size = sizeof(user_buffer); + if (::getpwuid_r(uid, &user_info, user_buffer, user_buffer_size, + &user_info_ptr) == 0) { + if (user_info_ptr) { + user_name.assign(user_info_ptr->pw_name); + return user_name.c_str(); } + } #endif - user_name.clear(); - return nullptr; + user_name.clear(); + return nullptr; } -const char * -HostInfoPosix::LookupGroupName(uint32_t gid, std::string &group_name) -{ +const char *HostInfoPosix::LookupGroupName(uint32_t gid, + std::string &group_name) { #ifndef __ANDROID__ - char group_buffer[PATH_MAX]; - size_t group_buffer_size = sizeof(group_buffer); - struct group group_info; - struct group *group_info_ptr = &group_info; - // Try the threadsafe version first - if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, &group_info_ptr) == 0) - { - if (group_info_ptr) - { - group_name.assign(group_info_ptr->gr_name); - return group_name.c_str(); - } + char group_buffer[PATH_MAX]; + size_t group_buffer_size = sizeof(group_buffer); + struct group group_info; + struct group *group_info_ptr = &group_info; + // Try the threadsafe version first + if (::getgrgid_r(gid, &group_info, group_buffer, group_buffer_size, + &group_info_ptr) == 0) { + if (group_info_ptr) { + group_name.assign(group_info_ptr->gr_name); + return group_name.c_str(); } - else - { - // The threadsafe version isn't currently working for me on darwin, but the non-threadsafe version - // is, so I am calling it below. - group_info_ptr = ::getgrgid(gid); - if (group_info_ptr) - { - group_name.assign(group_info_ptr->gr_name); - return group_name.c_str(); - } + } else { + // The threadsafe version isn't currently working for me on darwin, but the + // non-threadsafe version + // is, so I am calling it below. + group_info_ptr = ::getgrgid(gid); + if (group_info_ptr) { + group_name.assign(group_info_ptr->gr_name); + return group_name.c_str(); } - group_name.clear(); + } + group_name.clear(); #else - assert(false && "getgrgid_r() not supported on Android"); + assert(false && "getgrgid_r() not supported on Android"); #endif - return NULL; + return NULL; } -uint32_t -HostInfoPosix::GetUserID() -{ - return getuid(); -} +uint32_t HostInfoPosix::GetUserID() { return getuid(); } -uint32_t -HostInfoPosix::GetGroupID() -{ - return getgid(); -} +uint32_t HostInfoPosix::GetGroupID() { return getgid(); } -uint32_t -HostInfoPosix::GetEffectiveUserID() -{ - return geteuid(); -} +uint32_t HostInfoPosix::GetEffectiveUserID() { return geteuid(); } -uint32_t -HostInfoPosix::GetEffectiveGroupID() -{ - return getegid(); -} +uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); } -FileSpec -HostInfoPosix::GetDefaultShell() -{ - return FileSpec("/bin/sh", false); -} +FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh", false); } -bool -HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) -{ - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); +bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; + FileSpec lldb_file_spec; + if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + return false; - char raw_path[PATH_MAX]; - lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); + char raw_path[PATH_MAX]; + lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); + + // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with + // */bin as the base + // directory for helper exe programs. This will fail if the /lib and /bin + // directories are + // rooted in entirely different trees. + if (log) + log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to " + "derive the bin path (ePathTypeSupportExecutableDir) from " + "this path: %s", + raw_path); + char *lib_pos = ::strstr(raw_path, "/lib"); + if (lib_pos != nullptr) { + // Now write in bin in place of lib. + ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin"); - // Most Posix systems (e.g. Linux/*BSD) will attempt to replace a */lib with */bin as the base - // directory for helper exe programs. This will fail if the /lib and /bin directories are - // rooted in entirely different trees. if (log) - log->Printf("HostInfoPosix::ComputeSupportExeDirectory() attempting to derive the bin path (ePathTypeSupportExecutableDir) from " - "this path: %s", - raw_path); - char *lib_pos = ::strstr(raw_path, "/lib"); - if (lib_pos != nullptr) - { - // Now write in bin in place of lib. - ::snprintf(lib_pos, PATH_MAX - (lib_pos - raw_path), "/bin"); - - if (log) - log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, raw_path); - } - else - { - if (log) - log->Printf("Host::%s() failed to find /lib/liblldb within the shared lib path, bailing on bin path construction", - __FUNCTION__); - } - file_spec.GetDirectory().SetCString(raw_path); - return (bool)file_spec.GetDirectory(); + log->Printf("Host::%s() derived the bin path as: %s", __FUNCTION__, + raw_path); + } else { + if (log) + log->Printf("Host::%s() failed to find /lib/liblldb within the shared " + "lib path, bailing on bin path construction", + __FUNCTION__); + } + file_spec.GetDirectory().SetCString(raw_path); + return (bool)file_spec.GetDirectory(); } -bool -HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) -{ - FileSpec temp_file("/opt/local/include/lldb", false); - file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); - return true; +bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) { + FileSpec temp_file("/opt/local/include/lldb", false); + file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); + return true; } -bool -HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) -{ +bool HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) { #ifndef LLDB_DISABLE_PYTHON - FileSpec lldb_file_spec; - if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) - return false; + FileSpec lldb_file_spec; + if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec)) + return false; - char raw_path[PATH_MAX]; - lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); + char raw_path[PATH_MAX]; + lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); #if defined(LLDB_PYTHON_RELATIVE_LIBDIR) - // Build the path by backing out of the lib dir, then building - // with whatever the real python interpreter uses. (e.g. lib - // for most, lib64 on RHEL x86_64). - char python_path[PATH_MAX]; - ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path, LLDB_PYTHON_RELATIVE_LIBDIR); - - char final_path[PATH_MAX]; - realpath(python_path, final_path); - file_spec.GetDirectory().SetCString(final_path); - - return true; + // Build the path by backing out of the lib dir, then building + // with whatever the real python interpreter uses. (e.g. lib + // for most, lib64 on RHEL x86_64). + char python_path[PATH_MAX]; + ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path, + LLDB_PYTHON_RELATIVE_LIBDIR); + + char final_path[PATH_MAX]; + realpath(python_path, final_path); + file_spec.GetDirectory().SetCString(final_path); + + return true; #else - llvm::SmallString<256> python_version_dir; - llvm::raw_svector_ostream os(python_version_dir); - os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages"; + llvm::SmallString<256> python_version_dir; + llvm::raw_svector_ostream os(python_version_dir); + os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION + << "/site-packages"; - // We may get our string truncated. Should we protect this with an assert? - ::strncat(raw_path, python_version_dir.c_str(), sizeof(raw_path) - strlen(raw_path) - 1); + // We may get our string truncated. Should we protect this with an assert? + ::strncat(raw_path, python_version_dir.c_str(), + sizeof(raw_path) - strlen(raw_path) - 1); - file_spec.GetDirectory().SetCString(raw_path); - return true; + file_spec.GetDirectory().SetCString(raw_path); + return true; #endif #else - return false; + return false; #endif } -bool -HostInfoPosix::GetEnvironmentVar(const std::string &var_name, std::string &var) -{ - if (const char *pvar = ::getenv(var_name.c_str())) - { - var = std::string(pvar); - return true; - } - return false; +bool HostInfoPosix::GetEnvironmentVar(const std::string &var_name, + std::string &var) { + if (const char *pvar = ::getenv(var_name.c_str())) { + var = std::string(pvar); + return true; + } + return false; } diff --git a/lldb/source/Host/posix/HostProcessPosix.cpp b/lldb/source/Host/posix/HostProcessPosix.cpp index 93844d9b99d..9dd9fef94cd 100644 --- a/lldb/source/Host/posix/HostProcessPosix.cpp +++ b/lldb/source/Host/posix/HostProcessPosix.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Host.h" -#include "lldb/Host/posix/HostProcessPosix.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/posix/HostProcessPosix.h" #include "llvm/ADT/STLExtras.h" @@ -17,97 +17,77 @@ using namespace lldb_private; -namespace -{ - const int kInvalidPosixProcess = 0; +namespace { +const int kInvalidPosixProcess = 0; } HostProcessPosix::HostProcessPosix() - : HostNativeProcessBase(kInvalidPosixProcess) -{ -} + : HostNativeProcessBase(kInvalidPosixProcess) {} HostProcessPosix::HostProcessPosix(lldb::process_t process) - : HostNativeProcessBase(process) -{ -} + : HostNativeProcessBase(process) {} -HostProcessPosix::~HostProcessPosix() -{ -} +HostProcessPosix::~HostProcessPosix() {} -Error HostProcessPosix::Signal(int signo) const -{ - if (m_process == kInvalidPosixProcess) - { - Error error; - error.SetErrorString("HostProcessPosix refers to an invalid process"); - return error; - } +Error HostProcessPosix::Signal(int signo) const { + if (m_process == kInvalidPosixProcess) { + Error error; + error.SetErrorString("HostProcessPosix refers to an invalid process"); + return error; + } - return HostProcessPosix::Signal(m_process, signo); + return HostProcessPosix::Signal(m_process, signo); } -Error HostProcessPosix::Signal(lldb::process_t process, int signo) -{ - Error error; +Error HostProcessPosix::Signal(lldb::process_t process, int signo) { + Error error; - if (-1 == ::kill(process, signo)) - error.SetErrorToErrno(); + if (-1 == ::kill(process, signo)) + error.SetErrorToErrno(); - return error; + return error; } -Error HostProcessPosix::Terminate() -{ - return Signal(SIGKILL); -} +Error HostProcessPosix::Terminate() { return Signal(SIGKILL); } -Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const -{ - Error error; +Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const { + Error error; - // Use special code here because proc/[pid]/exe is a symbolic link. - char link_path[PATH_MAX]; - if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) != 1) - { - error.SetErrorString("Unable to build /proc/<pid>/exe string"); - return error; - } - - error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec); - if (!error.Success()) - return error; - - // If the binary has been deleted, the link name has " (deleted)" appended. - // Remove if there. - if (file_spec.GetFilename().GetStringRef().endswith(" (deleted)")) - { - const char *filename = file_spec.GetFilename().GetCString(); - static const size_t deleted_len = strlen(" (deleted)"); - const size_t len = file_spec.GetFilename().GetLength(); - file_spec.GetFilename().SetCStringWithLength(filename, len - deleted_len); - } + // Use special code here because proc/[pid]/exe is a symbolic link. + char link_path[PATH_MAX]; + if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_process) != 1) { + error.SetErrorString("Unable to build /proc/<pid>/exe string"); return error; -} + } -lldb::pid_t HostProcessPosix::GetProcessId() const -{ - return m_process; + error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec); + if (!error.Success()) + return error; + + // If the binary has been deleted, the link name has " (deleted)" appended. + // Remove if there. + if (file_spec.GetFilename().GetStringRef().endswith(" (deleted)")) { + const char *filename = file_spec.GetFilename().GetCString(); + static const size_t deleted_len = strlen(" (deleted)"); + const size_t len = file_spec.GetFilename().GetLength(); + file_spec.GetFilename().SetCStringWithLength(filename, len - deleted_len); + } + return error; } -bool HostProcessPosix::IsRunning() const -{ - if (m_process == kInvalidPosixProcess) - return false; +lldb::pid_t HostProcessPosix::GetProcessId() const { return m_process; } + +bool HostProcessPosix::IsRunning() const { + if (m_process == kInvalidPosixProcess) + return false; - // Send this process the null signal. If it succeeds the process is running. - Error error = Signal(0); - return error.Success(); + // Send this process the null signal. If it succeeds the process is running. + Error error = Signal(0); + return error.Success(); } -HostThread -HostProcessPosix::StartMonitoring(const Host::MonitorChildProcessCallback &callback, bool monitor_signals) -{ - return Host::StartMonitoringChildProcess(callback, m_process, monitor_signals); +HostThread HostProcessPosix::StartMonitoring( + const Host::MonitorChildProcessCallback &callback, bool monitor_signals) { + return Host::StartMonitoringChildProcess(callback, m_process, + monitor_signals); } diff --git a/lldb/source/Host/posix/HostThreadPosix.cpp b/lldb/source/Host/posix/HostThreadPosix.cpp index f1a6d6f8314..ac398998c20 100644 --- a/lldb/source/Host/posix/HostThreadPosix.cpp +++ b/lldb/source/Host/posix/HostThreadPosix.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Error.h" #include "lldb/Host/posix/HostThreadPosix.h" +#include "lldb/Core/Error.h" #include <errno.h> #include <pthread.h> @@ -16,67 +16,50 @@ using namespace lldb; using namespace lldb_private; -HostThreadPosix::HostThreadPosix() -{ -} +HostThreadPosix::HostThreadPosix() {} HostThreadPosix::HostThreadPosix(lldb::thread_t thread) - : HostNativeThreadBase(thread) -{ -} + : HostNativeThreadBase(thread) {} -HostThreadPosix::~HostThreadPosix() -{ -} +HostThreadPosix::~HostThreadPosix() {} -Error -HostThreadPosix::Join(lldb::thread_result_t *result) -{ - Error error; - if (IsJoinable()) - { - int err = ::pthread_join(m_thread, result); - error.SetError(err, lldb::eErrorTypePOSIX); - } - else - { - if (result) - *result = NULL; - error.SetError(EINVAL, eErrorTypePOSIX); - } +Error HostThreadPosix::Join(lldb::thread_result_t *result) { + Error error; + if (IsJoinable()) { + int err = ::pthread_join(m_thread, result); + error.SetError(err, lldb::eErrorTypePOSIX); + } else { + if (result) + *result = NULL; + error.SetError(EINVAL, eErrorTypePOSIX); + } - Reset(); - return error; + Reset(); + return error; } -Error -HostThreadPosix::Cancel() -{ - Error error; - if (IsJoinable()) - { +Error HostThreadPosix::Cancel() { + Error error; + if (IsJoinable()) { #ifndef __ANDROID__ #ifndef __FreeBSD__ - assert(false && "someone is calling HostThread::Cancel()"); + assert(false && "someone is calling HostThread::Cancel()"); #endif - int err = ::pthread_cancel(m_thread); - error.SetError(err, eErrorTypePOSIX); + int err = ::pthread_cancel(m_thread); + error.SetError(err, eErrorTypePOSIX); #else - error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); + error.SetErrorString("HostThreadPosix::Cancel() not supported on Android"); #endif - } - return error; + } + return error; } -Error -HostThreadPosix::Detach() -{ - Error error; - if (IsJoinable()) - { - int err = ::pthread_detach(m_thread); - error.SetError(err, eErrorTypePOSIX); - } - Reset(); - return error; +Error HostThreadPosix::Detach() { + Error error; + if (IsJoinable()) { + int err = ::pthread_detach(m_thread); + error.SetError(err, eErrorTypePOSIX); + } + Reset(); + return error; } diff --git a/lldb/source/Host/posix/LockFilePosix.cpp b/lldb/source/Host/posix/LockFilePosix.cpp index e52b648799b..d1cc617146d 100644 --- a/lldb/source/Host/posix/LockFilePosix.cpp +++ b/lldb/source/Host/posix/LockFilePosix.cpp @@ -14,64 +14,47 @@ using namespace lldb; using namespace lldb_private; -namespace -{ +namespace { -Error fileLock (int fd, int cmd, int lock_type, const uint64_t start, const uint64_t len) -{ - struct flock fl; +Error fileLock(int fd, int cmd, int lock_type, const uint64_t start, + const uint64_t len) { + struct flock fl; - fl.l_type = lock_type; - fl.l_whence = SEEK_SET; - fl.l_start = start; - fl.l_len = len; - fl.l_pid = ::getpid (); + fl.l_type = lock_type; + fl.l_whence = SEEK_SET; + fl.l_start = start; + fl.l_len = len; + fl.l_pid = ::getpid(); - Error error; - if (::fcntl (fd, cmd, &fl) == -1) - error.SetErrorToErrno (); + Error error; + if (::fcntl(fd, cmd, &fl) == -1) + error.SetErrorToErrno(); - return error; + return error; } -} // namespace +} // namespace -LockFilePosix::LockFilePosix (int fd) - : LockFileBase (fd) -{ -} +LockFilePosix::LockFilePosix(int fd) : LockFileBase(fd) {} -LockFilePosix::~LockFilePosix () -{ - Unlock (); -} +LockFilePosix::~LockFilePosix() { Unlock(); } -Error -LockFilePosix::DoWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLKW, F_WRLCK, start, len); +Error LockFilePosix::DoWriteLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLKW, F_WRLCK, start, len); } -Error -LockFilePosix::DoTryWriteLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLK, F_WRLCK, start, len); +Error LockFilePosix::DoTryWriteLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLK, F_WRLCK, start, len); } -Error -LockFilePosix::DoReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLKW, F_RDLCK, start, len); +Error LockFilePosix::DoReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLKW, F_RDLCK, start, len); } -Error -LockFilePosix::DoTryReadLock (const uint64_t start, const uint64_t len) -{ - return fileLock (m_fd, F_SETLK, F_RDLCK, start, len); +Error LockFilePosix::DoTryReadLock(const uint64_t start, const uint64_t len) { + return fileLock(m_fd, F_SETLK, F_RDLCK, start, len); } -Error -LockFilePosix::DoUnlock () -{ - return fileLock (m_fd, F_SETLK, F_UNLCK, m_start, m_len); +Error LockFilePosix::DoUnlock() { + return fileLock(m_fd, F_SETLK, F_UNLCK, m_start, m_len); } diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index 897f2d13c0c..b6325a55317 100644 --- a/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -18,176 +18,162 @@ using namespace lldb_private; static sig_atomic_t g_signal_flags[NSIG]; -static void -SignalHandler(int signo, siginfo_t *info, void *) -{ - assert(signo < NSIG); - g_signal_flags[signo] = 1; +static void SignalHandler(int signo, siginfo_t *info, void *) { + assert(signo < NSIG); + g_signal_flags[signo] = 1; } - -MainLoopPosix::~MainLoopPosix() -{ - assert(m_read_fds.size() == 0); - assert(m_signals.size() == 0); +MainLoopPosix::~MainLoopPosix() { + assert(m_read_fds.size() == 0); + assert(m_signals.size() == 0); } MainLoopPosix::ReadHandleUP -MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, const Callback &callback, Error &error) -{ - if (!object_sp || !object_sp->IsValid()) - { - error.SetErrorString("IO object is not valid."); - return nullptr; - } - - const bool inserted = m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; - if (! inserted) - { - error.SetErrorStringWithFormat("File descriptor %d already monitored.", - object_sp->GetWaitableHandle()); - return nullptr; - } - - return CreateReadHandle(object_sp); +MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, + const Callback &callback, Error &error) { + if (!object_sp || !object_sp->IsValid()) { + error.SetErrorString("IO object is not valid."); + return nullptr; + } + + const bool inserted = + m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; + if (!inserted) { + error.SetErrorStringWithFormat("File descriptor %d already monitored.", + object_sp->GetWaitableHandle()); + return nullptr; + } + + return CreateReadHandle(object_sp); } -// We shall block the signal, then install the signal handler. The signal will be unblocked in +// We shall block the signal, then install the signal handler. The signal will +// be unblocked in // the Run() function to check for signal delivery. MainLoopPosix::SignalHandleUP -MainLoopPosix::RegisterSignal(int signo, const Callback &callback, Error &error) -{ - if (m_signals.find(signo) != m_signals.end()) - { - error.SetErrorStringWithFormat("Signal %d already monitored.", signo); - return nullptr; - } +MainLoopPosix::RegisterSignal(int signo, const Callback &callback, + Error &error) { + if (m_signals.find(signo) != m_signals.end()) { + error.SetErrorStringWithFormat("Signal %d already monitored.", signo); + return nullptr; + } + + SignalInfo info; + info.callback = callback; + struct sigaction new_action; + new_action.sa_sigaction = &SignalHandler; + new_action.sa_flags = SA_SIGINFO; + sigemptyset(&new_action.sa_mask); + sigaddset(&new_action.sa_mask, signo); + + sigset_t old_set; + if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) { + error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", + ret); + return nullptr; + } + + info.was_blocked = sigismember(&old_set, signo); + if (sigaction(signo, &new_action, &info.old_action) == -1) { + error.SetErrorToErrno(); + if (!info.was_blocked) + pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr); + return nullptr; + } + + m_signals.insert({signo, info}); + g_signal_flags[signo] = 0; + + return SignalHandleUP(new SignalHandle(*this, signo)); +} - SignalInfo info; - info.callback = callback; - struct sigaction new_action; - new_action.sa_sigaction = &SignalHandler; - new_action.sa_flags = SA_SIGINFO; - sigemptyset(&new_action.sa_mask); - sigaddset(&new_action.sa_mask, signo); - - sigset_t old_set; - if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) - { - error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", ret); - return nullptr; - } +void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) { + bool erased = m_read_fds.erase(handle); + UNUSED_IF_ASSERT_DISABLED(erased); + assert(erased); +} - info.was_blocked = sigismember(&old_set, signo); - if (sigaction(signo, &new_action, &info.old_action) == -1) - { - error.SetErrorToErrno(); - if (!info.was_blocked) - pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr); - return nullptr; - } +void MainLoopPosix::UnregisterSignal(int signo) { + // We undo the actions of RegisterSignal on a best-effort basis. + auto it = m_signals.find(signo); + assert(it != m_signals.end()); - m_signals.insert({signo, info}); - g_signal_flags[signo] = 0; + sigaction(signo, &it->second.old_action, nullptr); - return SignalHandleUP(new SignalHandle(*this, signo)); -} + sigset_t set; + sigemptyset(&set); + sigaddset(&set, signo); + pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, + nullptr); -void -MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) -{ - bool erased = m_read_fds.erase(handle); - UNUSED_IF_ASSERT_DISABLED(erased); - assert(erased); + m_signals.erase(it); } -void -MainLoopPosix::UnregisterSignal(int signo) -{ - // We undo the actions of RegisterSignal on a best-effort basis. - auto it = m_signals.find(signo); - assert(it != m_signals.end()); +Error MainLoopPosix::Run() { + std::vector<int> signals; + sigset_t sigmask; + std::vector<int> read_fds; + fd_set read_fd_set; + m_terminate_request = false; + + // run until termination or until we run out of things to listen to + while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) { + // To avoid problems with callbacks changing the things we're supposed to + // listen to, we + // will store the *real* list of events separately. + signals.clear(); + read_fds.clear(); + FD_ZERO(&read_fd_set); + int nfds = 0; + + if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask)) + return Error("pthread_sigmask failed with error %d\n", ret); + + for (const auto &fd : m_read_fds) { + read_fds.push_back(fd.first); + FD_SET(fd.first, &read_fd_set); + nfds = std::max(nfds, fd.first + 1); + } - sigaction(signo, &it->second.old_action, nullptr); + for (const auto &sig : m_signals) { + signals.push_back(sig.first); + sigdelset(&sigmask, sig.first); + } - sigset_t set; - sigemptyset(&set); - sigaddset(&set, signo); - pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, nullptr); + if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == + -1 && + errno != EINTR) + return Error(errno, eErrorTypePOSIX); - m_signals.erase(it); -} + for (int sig : signals) { + if (g_signal_flags[sig] == 0) + continue; // No signal + g_signal_flags[sig] = 0; + + auto it = m_signals.find(sig); + if (it == m_signals.end()) + continue; // Signal must have gotten unregistered in the meantime + + it->second.callback(*this); // Do the work -Error -MainLoopPosix::Run() -{ - std::vector<int> signals; - sigset_t sigmask; - std::vector<int> read_fds; - fd_set read_fd_set; - m_terminate_request = false; - - // run until termination or until we run out of things to listen to - while (! m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) - { - // To avoid problems with callbacks changing the things we're supposed to listen to, we - // will store the *real* list of events separately. - signals.clear(); - read_fds.clear(); - FD_ZERO(&read_fd_set); - int nfds = 0; - - if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask)) - return Error("pthread_sigmask failed with error %d\n", ret); - - for (const auto &fd: m_read_fds) - { - read_fds.push_back(fd.first); - FD_SET(fd.first, &read_fd_set); - nfds = std::max(nfds, fd.first+1); - } - - for (const auto &sig: m_signals) - { - signals.push_back(sig.first); - sigdelset(&sigmask, sig.first); - } - - if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && errno != EINTR) - return Error(errno, eErrorTypePOSIX); - - for (int sig: signals) - { - if (g_signal_flags[sig] == 0) - continue; // No signal - g_signal_flags[sig] = 0; - - auto it = m_signals.find(sig); - if (it == m_signals.end()) - continue; // Signal must have gotten unregistered in the meantime - - it->second.callback(*this); // Do the work - - if (m_terminate_request) - return Error(); - } - - for (int fd: read_fds) - { - if (!FD_ISSET(fd, &read_fd_set)) - continue; // Not ready - - auto it = m_read_fds.find(fd); - if (it == m_read_fds.end()) - continue; // File descriptor must have gotten unregistered in the meantime - - it->second(*this); // Do the work - - if (m_terminate_request) - return Error(); - } + if (m_terminate_request) + return Error(); } - return Error(); -} + for (int fd : read_fds) { + if (!FD_ISSET(fd, &read_fd_set)) + continue; // Not ready + + auto it = m_read_fds.find(fd); + if (it == m_read_fds.end()) + continue; // File descriptor must have gotten unregistered in the + // meantime + + it->second(*this); // Do the work + if (m_terminate_request) + return Error(); + } + } + return Error(); +} diff --git a/lldb/source/Host/posix/PipePosix.cpp b/lldb/source/Host/posix/PipePosix.cpp index 6695bbfbac7..a653b3eae73 100644 --- a/lldb/source/Host/posix/PipePosix.cpp +++ b/lldb/source/Host/posix/PipePosix.cpp @@ -26,9 +26,9 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> -#include <unistd.h> -#include <sys/types.h> #include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> using namespace lldb; using namespace lldb_private; @@ -39,343 +39,280 @@ enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE // pipe2 is supported by a limited set of platforms // TODO: Add more platforms that support pipe2. -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__) +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ + defined(__NetBSD__) #define PIPE2_SUPPORTED 1 #else #define PIPE2_SUPPORTED 0 #endif -namespace -{ +namespace { constexpr auto OPEN_WRITER_SLEEP_TIMEOUT_MSECS = 100; #if defined(FD_CLOEXEC) && !PIPE2_SUPPORTED -bool SetCloexecFlag(int fd) -{ - int flags = ::fcntl(fd, F_GETFD); - if (flags == -1) - return false; - return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); +bool SetCloexecFlag(int fd) { + int flags = ::fcntl(fd, F_GETFD); + if (flags == -1) + return false; + return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); } #endif -std::chrono::time_point<std::chrono::steady_clock> -Now() -{ - return std::chrono::steady_clock::now(); +std::chrono::time_point<std::chrono::steady_clock> Now() { + return std::chrono::steady_clock::now(); } - } PipePosix::PipePosix() - : m_fds{ - PipePosix::kInvalidDescriptor, - PipePosix::kInvalidDescriptor - } {} + : m_fds{PipePosix::kInvalidDescriptor, PipePosix::kInvalidDescriptor} {} -PipePosix::PipePosix(int read_fd, int write_fd) - : m_fds{read_fd, write_fd} {} +PipePosix::PipePosix(int read_fd, int write_fd) : m_fds{read_fd, write_fd} {} PipePosix::PipePosix(PipePosix &&pipe_posix) : PipeBase{std::move(pipe_posix)}, - m_fds{ - pipe_posix.ReleaseReadFileDescriptor(), - pipe_posix.ReleaseWriteFileDescriptor() - } {} - -PipePosix &PipePosix::operator=(PipePosix &&pipe_posix) -{ - PipeBase::operator=(std::move(pipe_posix)); - m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor(); - m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor(); - return *this; + m_fds{pipe_posix.ReleaseReadFileDescriptor(), + pipe_posix.ReleaseWriteFileDescriptor()} {} + +PipePosix &PipePosix::operator=(PipePosix &&pipe_posix) { + PipeBase::operator=(std::move(pipe_posix)); + m_fds[READ] = pipe_posix.ReleaseReadFileDescriptor(); + m_fds[WRITE] = pipe_posix.ReleaseWriteFileDescriptor(); + return *this; } -PipePosix::~PipePosix() -{ - Close(); -} +PipePosix::~PipePosix() { Close(); } -Error -PipePosix::CreateNew(bool child_processes_inherit) -{ - if (CanRead() || CanWrite()) - return Error(EINVAL, eErrorTypePOSIX); +Error PipePosix::CreateNew(bool child_processes_inherit) { + if (CanRead() || CanWrite()) + return Error(EINVAL, eErrorTypePOSIX); - Error error; + Error error; #if PIPE2_SUPPORTED - if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0) - return error; + if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC) == 0) + return error; #else - if (::pipe(m_fds) == 0) - { + if (::pipe(m_fds) == 0) { #ifdef FD_CLOEXEC - if (!child_processes_inherit) - { - if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) - { - error.SetErrorToErrno(); - Close(); - return error; - } - } -#endif + if (!child_processes_inherit) { + if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) { + error.SetErrorToErrno(); + Close(); return error; + } } #endif - - error.SetErrorToErrno(); - m_fds[READ] = PipePosix::kInvalidDescriptor; - m_fds[WRITE] = PipePosix::kInvalidDescriptor; return error; + } +#endif + + error.SetErrorToErrno(); + m_fds[READ] = PipePosix::kInvalidDescriptor; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + return error; } -Error -PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) -{ - if (CanRead() || CanWrite()) - return Error("Pipe is already opened"); +Error PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) { + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); - Error error; - if (::mkfifo(name.data(), 0660) != 0) - error.SetErrorToErrno(); + Error error; + if (::mkfifo(name.data(), 0660) != 0) + error.SetErrorToErrno(); - return error; + return error; } -Error -PipePosix::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char>& name) -{ - llvm::SmallString<PATH_MAX> named_pipe_path; - llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); - FileSpec tmpdir_file_spec; - tmpdir_file_spec.Clear(); - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } - else - { - tmpdir_file_spec.AppendPathComponent("/tmp"); - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } - - // It's possible that another process creates the target path after we've - // verified it's available but before we create it, in which case we - // should try again. - Error error; - do { - llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), named_pipe_path); - error = CreateNew(named_pipe_path, child_process_inherit); - } while (error.GetError() == EEXIST); - - if (error.Success()) - name = named_pipe_path; - return error; +Error PipePosix::CreateWithUniqueName(llvm::StringRef prefix, + bool child_process_inherit, + llvm::SmallVectorImpl<char> &name) { + llvm::SmallString<PATH_MAX> named_pipe_path; + llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); + FileSpec tmpdir_file_spec; + tmpdir_file_spec.Clear(); + if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } else { + tmpdir_file_spec.AppendPathComponent("/tmp"); + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } + + // It's possible that another process creates the target path after we've + // verified it's available but before we create it, in which case we + // should try again. + Error error; + do { + llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), + named_pipe_path); + error = CreateNew(named_pipe_path, child_process_inherit); + } while (error.GetError() == EEXIST); + + if (error.Success()) + name = named_pipe_path; + return error; } -Error -PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) -{ - if (CanRead() || CanWrite()) - return Error("Pipe is already opened"); +Error PipePosix::OpenAsReader(llvm::StringRef name, + bool child_process_inherit) { + if (CanRead() || CanWrite()) + return Error("Pipe is already opened"); - int flags = O_RDONLY | O_NONBLOCK; - if (!child_process_inherit) - flags |= O_CLOEXEC; + 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.SetErrorToErrno(); + Error error; + int fd = ::open(name.data(), flags); + if (fd != -1) + m_fds[READ] = fd; + else + error.SetErrorToErrno(); - return error; + return error; } -Error -PipePosix::OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) -{ - if (CanRead() || CanWrite()) - 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; - } +Error PipePosix::OpenAsWriterWithTimeout( + llvm::StringRef name, bool child_process_inherit, + const std::chrono::microseconds &timeout) { + if (CanRead() || CanWrite()) + 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"); } - return Error(); -} + 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; + } + } -int -PipePosix::GetReadFileDescriptor() const -{ - return m_fds[READ]; + return Error(); } -int -PipePosix::GetWriteFileDescriptor() const -{ - return m_fds[WRITE]; -} +int PipePosix::GetReadFileDescriptor() const { return m_fds[READ]; } -int -PipePosix::ReleaseReadFileDescriptor() -{ - const int fd = m_fds[READ]; - m_fds[READ] = PipePosix::kInvalidDescriptor; - return fd; +int PipePosix::GetWriteFileDescriptor() const { return m_fds[WRITE]; } + +int PipePosix::ReleaseReadFileDescriptor() { + const int fd = m_fds[READ]; + m_fds[READ] = PipePosix::kInvalidDescriptor; + return fd; } -int -PipePosix::ReleaseWriteFileDescriptor() -{ - const int fd = m_fds[WRITE]; - m_fds[WRITE] = PipePosix::kInvalidDescriptor; - return fd; +int PipePosix::ReleaseWriteFileDescriptor() { + const int fd = m_fds[WRITE]; + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + return fd; } -void -PipePosix::Close() -{ - CloseReadFileDescriptor(); - CloseWriteFileDescriptor(); +void PipePosix::Close() { + CloseReadFileDescriptor(); + CloseWriteFileDescriptor(); } -Error -PipePosix::Delete(llvm::StringRef name) -{ - return FileSystem::Unlink(FileSpec{name.data(), true}); +Error PipePosix::Delete(llvm::StringRef name) { + return FileSystem::Unlink(FileSpec{name.data(), true}); } -bool -PipePosix::CanRead() const -{ - return m_fds[READ] != PipePosix::kInvalidDescriptor; +bool PipePosix::CanRead() const { + return m_fds[READ] != PipePosix::kInvalidDescriptor; } -bool -PipePosix::CanWrite() const -{ - return m_fds[WRITE] != PipePosix::kInvalidDescriptor; +bool PipePosix::CanWrite() const { + return m_fds[WRITE] != PipePosix::kInvalidDescriptor; } -void -PipePosix::CloseReadFileDescriptor() -{ - if (CanRead()) - { - close(m_fds[READ]); - m_fds[READ] = PipePosix::kInvalidDescriptor; - } +void PipePosix::CloseReadFileDescriptor() { + if (CanRead()) { + close(m_fds[READ]); + m_fds[READ] = PipePosix::kInvalidDescriptor; + } } -void -PipePosix::CloseWriteFileDescriptor() -{ - if (CanWrite()) - { - close(m_fds[WRITE]); - m_fds[WRITE] = PipePosix::kInvalidDescriptor; - } +void PipePosix::CloseWriteFileDescriptor() { + if (CanWrite()) { + close(m_fds[WRITE]); + m_fds[WRITE] = PipePosix::kInvalidDescriptor; + } } -Error -PipePosix::ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) -{ - bytes_read = 0; - if (!CanRead()) - return Error(EINVAL, eErrorTypePOSIX); - - const int fd = GetReadFileDescriptor(); - - SelectHelper select_helper; - select_helper.SetTimeout(timeout); - select_helper.FDSetRead(fd); - - Error error; - while (error.Success()) - { - error = select_helper.Select(); - if (error.Success()) - { - auto result = ::read(fd, reinterpret_cast<char*>(buf) + bytes_read, size - bytes_read); - if (result != -1) - { - bytes_read += result; - if (bytes_read == size || result == 0) - break; - } - else - { - error.SetErrorToErrno(); - break; - } - } +Error PipePosix::ReadWithTimeout(void *buf, size_t size, + const std::chrono::microseconds &timeout, + size_t &bytes_read) { + bytes_read = 0; + if (!CanRead()) + return Error(EINVAL, eErrorTypePOSIX); + + const int fd = GetReadFileDescriptor(); + + SelectHelper select_helper; + select_helper.SetTimeout(timeout); + select_helper.FDSetRead(fd); + + Error error; + while (error.Success()) { + error = select_helper.Select(); + if (error.Success()) { + auto result = ::read(fd, reinterpret_cast<char *>(buf) + bytes_read, + size - bytes_read); + if (result != -1) { + bytes_read += result; + if (bytes_read == size || result == 0) + break; + } else { + error.SetErrorToErrno(); + break; + } } - return error; + } + return error; } -Error -PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) -{ - bytes_written = 0; - if (!CanWrite()) - return Error(EINVAL, eErrorTypePOSIX); - - const int fd = GetWriteFileDescriptor(); - SelectHelper select_helper; - select_helper.SetTimeout(std::chrono::seconds(0)); - select_helper.FDSetWrite(fd); - - Error error; - while (error.Success()) - { - error = select_helper.Select(); - if (error.Success()) - { - auto result = ::write(fd, reinterpret_cast<const char*>(buf) + bytes_written, size - bytes_written); - if (result != -1) - { - bytes_written += result; - if (bytes_written == size) - break; - } - else - { - error.SetErrorToErrno(); - } - } +Error PipePosix::Write(const void *buf, size_t size, size_t &bytes_written) { + bytes_written = 0; + if (!CanWrite()) + return Error(EINVAL, eErrorTypePOSIX); + + const int fd = GetWriteFileDescriptor(); + SelectHelper select_helper; + select_helper.SetTimeout(std::chrono::seconds(0)); + select_helper.FDSetWrite(fd); + + Error error; + while (error.Success()) { + error = select_helper.Select(); + if (error.Success()) { + auto result = + ::write(fd, reinterpret_cast<const char *>(buf) + bytes_written, + size - bytes_written); + if (result != -1) { + bytes_written += result; + if (bytes_written == size) + break; + } else { + error.SetErrorToErrno(); + } } - return error; + } + return error; } diff --git a/lldb/source/Host/posix/ProcessLauncherPosix.cpp b/lldb/source/Host/posix/ProcessLauncherPosix.cpp index dd5c5121a97..f90bf0cd88a 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosix.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosix.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Host/posix/ProcessLauncherPosix.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostProcess.h" -#include "lldb/Host/posix/ProcessLauncherPosix.h" #include "lldb/Target/ProcessLaunchInfo.h" @@ -19,15 +19,16 @@ using namespace lldb; using namespace lldb_private; HostProcess -ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) -{ - lldb::pid_t pid; - char exe_path[PATH_MAX]; +ProcessLauncherPosix::LaunchProcess(const ProcessLaunchInfo &launch_info, + Error &error) { + lldb::pid_t pid; + char exe_path[PATH_MAX]; - launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); + launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); - // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make MacOSX re-use this - // ProcessLauncher when it wants a posix_spawn launch. - error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid); - return HostProcess(pid); + // TODO(zturner): Move the code from LaunchProcessPosixSpawn to here, and make + // MacOSX re-use this + // ProcessLauncher when it wants a posix_spawn launch. + error = Host::LaunchProcessPosixSpawn(exe_path, launch_info, pid); + return HostProcess(pid); } |

