Coverage Report

Created: 2026-04-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmDebuggerPosixPipeConnection.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmDebuggerPosixPipeConnection.h"
4
5
#include <cerrno>
6
#include <cstring>
7
#include <stdexcept>
8
#include <utility>
9
10
#include <unistd.h>
11
12
#include <sys/socket.h>
13
#include <sys/types.h>
14
15
namespace cmDebugger {
16
17
#ifndef _WIN32
18
19
cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX(
20
  std::string name)
21
0
  : PipeName(std::move(name))
22
0
{
23
0
  addr.sun_path[0] = '\0';
24
0
}
Unexecuted instantiation: cmDebugger::cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Unexecuted instantiation: cmDebugger::cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
25
26
cmDebuggerPipeConnection_POSIX::~cmDebuggerPipeConnection_POSIX()
27
0
{
28
0
  if (isOpen()) {
29
0
    close();
30
0
  }
31
0
}
32
33
bool cmDebuggerPipeConnection_POSIX::StartListening(std::string& errorMessage)
34
0
{
35
0
  listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
36
0
  if (listen_fd < 0) {
37
0
    errorMessage = "Failed to create socket: ";
38
0
    errorMessage += strerror(errno);
39
0
    return false;
40
0
  }
41
42
0
  addr.sun_family = AF_UNIX;
43
0
  strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path));
44
0
  addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
45
0
  if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) == -1) {
46
0
    errorMessage = "Failed to bind name '";
47
0
    errorMessage += addr.sun_path;
48
0
    errorMessage += "' to socket: ";
49
0
    errorMessage += strerror(errno);
50
0
    close_listen();
51
0
    return false;
52
0
  }
53
54
0
  if (listen(listen_fd, 1) == -1) {
55
0
    errorMessage = "Failed to listen on socket: ";
56
0
    errorMessage += strerror(errno);
57
0
    close_listen();
58
0
    return false;
59
0
  }
60
61
0
  StartedListening.set_value();
62
0
  return true;
63
0
}
64
65
std::shared_ptr<dap::Reader> cmDebuggerPipeConnection_POSIX::GetReader()
66
0
{
67
0
  return std::static_pointer_cast<dap::Reader>(shared_from_this());
68
0
}
69
70
std::shared_ptr<dap::Writer> cmDebuggerPipeConnection_POSIX::GetWriter()
71
0
{
72
0
  return std::static_pointer_cast<dap::Writer>(shared_from_this());
73
0
}
74
75
bool cmDebuggerPipeConnection_POSIX::isOpen()
76
0
{
77
0
  return rw_pipe >= 0;
78
0
}
79
80
void cmDebuggerPipeConnection_POSIX::close()
81
0
{
82
0
  close_listen();
83
0
  ::close(rw_pipe);
84
0
  rw_pipe = -1;
85
0
}
86
87
void cmDebuggerPipeConnection_POSIX::close_listen()
88
0
{
89
0
  if (strlen(addr.sun_path) > 0) {
90
0
    unlink(addr.sun_path);
91
0
    addr.sun_path[0] = '\0';
92
0
  }
93
0
  ::close(listen_fd);
94
0
  listen_fd = -1;
95
0
}
96
97
void cmDebuggerPipeConnection_POSIX::WaitForConnection()
98
0
{
99
0
  sockaddr_un laddr;
100
0
  socklen_t len = sizeof(laddr);
101
0
  rw_pipe = accept(listen_fd, (sockaddr*)&laddr, &len);
102
0
  if (rw_pipe < 0) {
103
0
    close();
104
0
    return;
105
0
  }
106
107
0
  close_listen(); // no longer need the listen resources
108
0
}
109
110
size_t cmDebuggerPipeConnection_POSIX::read(void* buffer, size_t n)
111
0
{
112
0
  size_t result = 0;
113
0
  if (rw_pipe >= 0) {
114
0
    ssize_t count = ::read(rw_pipe, buffer, n);
115
0
    if (count <= 0) {
116
      // EOF or error (including EBADF from a concurrent close).
117
0
      close();
118
0
      return 0;
119
0
    }
120
0
    result = static_cast<size_t>(count);
121
0
  }
122
123
0
  return result;
124
0
}
125
126
bool cmDebuggerPipeConnection_POSIX::write(void const* buffer, size_t n)
127
0
{
128
0
  bool result = false;
129
0
  if (rw_pipe >= 0) {
130
0
    result = ::write(rw_pipe, buffer, n) >= 0;
131
0
    if (!result) {
132
0
      close();
133
0
    }
134
0
  }
135
136
0
  return result;
137
0
}
138
139
cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::string name)
140
0
  : PipeName(std::move(name))
141
0
{
142
0
}
Unexecuted instantiation: cmDebugger::cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
Unexecuted instantiation: cmDebugger::cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
143
144
cmDebuggerPipeClient_POSIX::~cmDebuggerPipeClient_POSIX()
145
0
{
146
0
  close();
147
0
}
148
149
void cmDebuggerPipeClient_POSIX::WaitForConnection()
150
0
{
151
0
  rw_pipe = socket(AF_UNIX, SOCK_STREAM, 0);
152
0
  if (rw_pipe < 0) {
153
0
    throw std::runtime_error(std::string("Failed to create socket: ") +
154
0
                             strerror(errno));
155
0
  }
156
157
0
  sockaddr_un addr;
158
0
  addr.sun_family = AF_UNIX;
159
0
  strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path));
160
0
  addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
161
0
  if (connect(rw_pipe, (sockaddr*)&addr, sizeof(addr)) == -1) {
162
0
    close();
163
0
    throw std::runtime_error(
164
0
      std::string("Failed to connect path to socket: ") + strerror(errno));
165
0
  }
166
0
}
167
168
bool cmDebuggerPipeClient_POSIX::isOpen()
169
0
{
170
0
  return rw_pipe >= 0;
171
0
}
172
173
void cmDebuggerPipeClient_POSIX::close()
174
0
{
175
0
  if (isOpen()) {
176
0
    ::close(rw_pipe);
177
0
    rw_pipe = -1;
178
0
  }
179
0
}
180
181
void cmDebuggerPipeClient_POSIX::ShutdownForTesting()
182
0
{
183
0
  if (isOpen()) {
184
0
    ::shutdown(rw_pipe, SHUT_RDWR);
185
0
  }
186
0
}
187
188
size_t cmDebuggerPipeClient_POSIX::read(void* buffer, size_t n)
189
0
{
190
0
  ssize_t count = 0;
191
0
  if (isOpen()) {
192
0
    count = ::read(rw_pipe, buffer, n);
193
0
    if (count <= 0) {
194
      // EOF or error (including EBADF from a concurrent close).
195
0
      close();
196
0
      return 0;
197
0
    }
198
0
  }
199
200
0
  return static_cast<size_t>(count);
201
0
}
202
203
bool cmDebuggerPipeClient_POSIX::write(void const* buffer, size_t n)
204
0
{
205
0
  int count = 0;
206
0
  if (isOpen()) {
207
0
    count = static_cast<int>(::write(rw_pipe, buffer, n));
208
0
    if (count < 0) {
209
0
      close();
210
0
    }
211
0
  }
212
213
0
  return count > 0;
214
0
}
215
216
#endif // !_WIN32
217
218
} // namespace cmDebugger