summaryrefslogtreecommitdiffstats
path: root/Source/cmDebuggerPosixPipeConnection.cxx
diff options
context:
space:
mode:
authorPaul Maybee <paulmay@microsoft.com>2023-07-29 17:23:43 (GMT)
committerBrad King <brad.king@kitware.com>2023-08-17 14:11:33 (GMT)
commit8b1257e7bf821461e6e0d92bf57e1c4ed885ddf9 (patch)
tree9ce28af2bff1b6c1d6f97f3e105849d3fe7829f4 /Source/cmDebuggerPosixPipeConnection.cxx
parentb0054dd65c1d69a437abe85d27e704326884a9c2 (diff)
downloadCMake-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.cxx205
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