/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 |