diff options
author | Paul Maybee <paulmay@microsoft.com> | 2023-07-29 17:23:43 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-08-17 14:11:33 (GMT) |
commit | 8b1257e7bf821461e6e0d92bf57e1c4ed885ddf9 (patch) | |
tree | 9ce28af2bff1b6c1d6f97f3e105849d3fe7829f4 /Source/cmDebuggerPosixPipeConnection.cxx | |
parent | b0054dd65c1d69a437abe85d27e704326884a9c2 (diff) | |
download | CMake-8b1257e7bf821461e6e0d92bf57e1c4ed885ddf9.zip CMake-8b1257e7bf821461e6e0d92bf57e1c4ed885ddf9.tar.gz CMake-8b1257e7bf821461e6e0d92bf57e1c4ed885ddf9.tar.bz2 |
Debugger: Replace libuv with platform-specific connection code
Remove libuv usage from CMake debugger. Libuv has an async io model
and cppdap uses a sync model, so an extra thread and a buffer copy
were necessary to match semantics. In order to eliminate those
costs this commit implements the IO using platform specific APIs.
Diffstat (limited to 'Source/cmDebuggerPosixPipeConnection.cxx')
-rw-r--r-- | Source/cmDebuggerPosixPipeConnection.cxx | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/Source/cmDebuggerPosixPipeConnection.cxx b/Source/cmDebuggerPosixPipeConnection.cxx new file mode 100644 index 0000000..0587450 --- /dev/null +++ b/Source/cmDebuggerPosixPipeConnection.cxx @@ -0,0 +1,205 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmDebuggerPosixPipeConnection.h" + +#include <cerrno> +#include <cstring> +#include <stdexcept> +#include <utility> + +#include <unistd.h> + +#include <sys/socket.h> + +namespace cmDebugger { + +#ifndef _WIN32 + +cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX( + std::string name) + : PipeName(std::move(name)) +{ + addr.sun_path[0] = '\0'; +} + +cmDebuggerPipeConnection_POSIX::~cmDebuggerPipeConnection_POSIX() +{ + if (isOpen()) { + close(); + } +} + +bool cmDebuggerPipeConnection_POSIX::StartListening(std::string& errorMessage) +{ + listen_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (listen_fd < 0) { + errorMessage = "Failed to create socket: "; + errorMessage += strerror(errno); + return false; + } + + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path)); + addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; + if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) == -1) { + errorMessage = "Failed to bind name '"; + errorMessage += addr.sun_path; + errorMessage += "' to socket: "; + errorMessage += strerror(errno); + close_listen(); + return false; + } + + if (listen(listen_fd, 1) == -1) { + errorMessage = "Failed to listen on socket: "; + errorMessage += strerror(errno); + close_listen(); + return false; + } + + StartedListening.set_value(); + return true; +} + +std::shared_ptr<dap::Reader> cmDebuggerPipeConnection_POSIX::GetReader() +{ + return std::static_pointer_cast<dap::Reader>(shared_from_this()); +} + +std::shared_ptr<dap::Writer> cmDebuggerPipeConnection_POSIX::GetWriter() +{ + return std::static_pointer_cast<dap::Writer>(shared_from_this()); +} + +bool cmDebuggerPipeConnection_POSIX::isOpen() +{ + return rw_pipe >= 0; +} + +void cmDebuggerPipeConnection_POSIX::close() +{ + close_listen(); + ::close(rw_pipe); + rw_pipe = -1; +} + +void cmDebuggerPipeConnection_POSIX::close_listen() +{ + if (strlen(addr.sun_path) > 0) { + unlink(addr.sun_path); + addr.sun_path[0] = '\0'; + } + ::close(listen_fd); + listen_fd = -1; +} + +void cmDebuggerPipeConnection_POSIX::WaitForConnection() +{ + sockaddr_un laddr; + socklen_t len = sizeof(laddr); + rw_pipe = accept(listen_fd, (sockaddr*)&laddr, &len); + if (rw_pipe < 0) { + close(); + return; + } + + close_listen(); // no longer need the listen resources +} + +size_t cmDebuggerPipeConnection_POSIX::read(void* buffer, size_t n) +{ + size_t result = 0; + if (rw_pipe >= 0) { + result = ::read(rw_pipe, buffer, n); + if (result == 0) { + close(); + } + } + + return result; +} + +bool cmDebuggerPipeConnection_POSIX::write(void const* buffer, size_t n) +{ + bool result = false; + if (rw_pipe >= 0) { + result = ::write(rw_pipe, buffer, n) >= 0; + if (!result) { + close(); + } + } + + return result; +} + +cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::string name) + : PipeName(std::move(name)) +{ +} + +cmDebuggerPipeClient_POSIX::~cmDebuggerPipeClient_POSIX() +{ + close(); +} + +void cmDebuggerPipeClient_POSIX::WaitForConnection() +{ + rw_pipe = socket(AF_UNIX, SOCK_STREAM, 0); + if (rw_pipe < 0) { + throw std::runtime_error(std::string("Failed to create socket: ") + + strerror(errno)); + } + + sockaddr_un addr; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path)); + addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; + if (connect(rw_pipe, (sockaddr*)&addr, sizeof(addr)) == -1) { + close(); + throw std::runtime_error( + std::string("Failed to connect path to socket: ") + strerror(errno)); + } +} + +bool cmDebuggerPipeClient_POSIX::isOpen() +{ + return rw_pipe >= 0; +} + +void cmDebuggerPipeClient_POSIX::close() +{ + if (isOpen()) { + ::close(rw_pipe); + rw_pipe = -1; + } +} + +size_t cmDebuggerPipeClient_POSIX::read(void* buffer, size_t n) +{ + int count = 0; + if (isOpen()) { + count = static_cast<int>(::read(rw_pipe, buffer, n)); + if (count == 0) { + close(); + } + } + + return count; +} + +bool cmDebuggerPipeClient_POSIX::write(void const* buffer, size_t n) +{ + int count = 0; + if (isOpen()) { + count = static_cast<int>(::write(rw_pipe, buffer, n)); + if (count < 0) { + close(); + } + } + + return count > 0; +} + +#endif // !_WIN32 + +} // namespace cmDebugger |