Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: src/trusted/debug_stub/transport_ipc.cc

Issue 1867633002: Revert "Debug Stub: Added support for windows in ipc_transport." (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/trusted/debug_stub/build.scons ('k') | src/trusted/debug_stub/transport_ipc_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2015 The Native Client Authors. All rights reserved. 2 * Copyright (c) 2015 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <string.h> 9 #include <string.h>
10 10
11 #include <algorithm> 11 #include <algorithm>
12 #include <string> 12 #include <string>
13 13
14 #include "native_client/src/include/build_config.h" 14 #include "native_client/src/include/build_config.h"
15 #include "native_client/src/include/nacl_scoped_ptr.h" 15 #include "native_client/src/include/nacl_scoped_ptr.h"
16 #include "native_client/src/shared/platform/nacl_check.h" 16 #include "native_client/src/shared/platform/nacl_check.h"
17 #include "native_client/src/shared/platform/nacl_log.h" 17 #include "native_client/src/shared/platform/nacl_log.h"
18 #include "native_client/src/trusted/debug_stub/transport.h" 18 #include "native_client/src/trusted/debug_stub/transport.h"
19 #include "native_client/src/trusted/service_runtime/sel_ldr.h" 19 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
20 20
21 #if NACL_WINDOWS
22 #include <windows.h>
23 #endif
24 21
25 namespace port { 22 namespace port {
26 23
27 // This transport is to handle connections over ipc to another 24 // This transport is to handle connections over ipc to another
28 // process. Instead of directly talking over a server socket, 25 // process. Instead of directly talking over a server socket,
29 // the server socket is listening on the other process and 26 // the server socket is listening on the other process and
30 // ferries the data between the socket and the given pipe. 27 // ferries the data between the socket and the given pipe.
31 // 28 //
32 // Since we also need to handle multiple sequential connections 29 // Since we also need to handle multiple sequential connections
33 // but cannot close our handle the incoming data is encoded. 30 // but cannot close our handle the incoming data is encoded.
34 // The encoding is simple and just prepends a 4 byte length 31 // The encoding is simple and just prepends a 4 byte length
35 // to each message. A length of -1 signifies that the server 32 // to each message. A length of -1 signifies that the server
36 // socket was disconnected and is awaiting a new connection. 33 // socket was disconnected and is awaiting a new connection.
37 // Once in a disconnected state any new incoming data will 34 // Once in a disconnected state any new incoming data will
38 // symbolize a new connection. 35 // symbolize a new connection.
36
37 // TODO(leslieb): implement for windows.
38 #if NACL_LINUX || NACL_OSX
39 class TransportIPC : public ITransport { 39 class TransportIPC : public ITransport {
40 public: 40 public:
41 TransportIPC() 41 TransportIPC()
42 : buf_(new char[kBufSize]), 42 : buf_(new char[kBufSize]),
43 unconsumed_bytes_(0), 43 unconsumed_bytes_(0),
44 bytes_to_read_(kServerSocketDisconnect), 44 bytes_to_read_(kServerSocketDisconnect),
45 handle_(NACL_INVALID_HANDLE) { } 45 handle_(NACL_INVALID_HANDLE) { }
46 46
47 explicit TransportIPC(NaClHandle fd) 47 explicit TransportIPC(NaClHandle fd)
48 : buf_(new char[kBufSize]), 48 : buf_(new char[kBufSize]),
49 unconsumed_bytes_(0), 49 unconsumed_bytes_(0),
50 bytes_to_read_(kServerSocketDisconnect), 50 bytes_to_read_(kServerSocketDisconnect),
51 handle_(fd) { } 51 handle_(fd) { }
52 52
53 ~TransportIPC() { 53 ~TransportIPC() {
54 if (handle_ != NACL_INVALID_HANDLE) { 54 if (handle_ != NACL_INVALID_HANDLE) {
55 #if NACL_WINDOWS
56 if (!CloseHandle(handle_))
57 #else
58 if (::close(handle_)) 55 if (::close(handle_))
59 #endif
60 NaClLog(LOG_FATAL, 56 NaClLog(LOG_FATAL,
61 "TransportIPC::Disconnect: Failed to close handle.\n"); 57 "TransportIPC::Disconnect: Failed to close handle.\n");
62 } 58 }
63 } 59 }
64 60
65 // Read from this transport, return true on success. 61 // Read from this transport, return true on success.
66 // Returning false means we have disconnected on the server end. 62 // Returning false means we have disconnected on the server end.
67 virtual bool Read(void *ptr, int32_t len) { 63 virtual bool Read(void *ptr, int32_t len) {
68 CHECK(IsConnected()); 64 CHECK(IsConnected());
69 CHECK(ptr && len >= 0); 65 CHECK(ptr && len >= 0);
70 char *dst = static_cast<char *>(ptr); 66 char *dst = static_cast<char *>(ptr);
71 67
72 while (len > 0) { 68 while (len > 0) {
73 if (!FillBufferIfEmpty()) return false; 69 if (!FillBufferIfEmpty()) return false;
74 CopyFromBuffer(&dst, &len); 70 CopyFromBuffer(&dst, &len);
75 } 71 }
76 return true; 72 return true;
77 } 73 }
78 74
79 // Write to this transport, return true on success. 75 // Write to this transport, return true on success.
80 virtual bool Write(const void *ptr, int32_t len) { 76 virtual bool Write(const void *ptr, int32_t len) {
81 CHECK(IsConnected()); 77 CHECK(IsConnected());
82 CHECK(ptr && len >= 0); 78 CHECK(ptr && len >= 0);
83 const char *src = static_cast<const char *>(ptr); 79 const char *src = static_cast<const char *>(ptr);
84 while (len > 0) { 80 while (len > 0) {
85 int result = WriteInternal(handle_, src, len); 81 int result = ::write(handle_, src, len);
86 if (result >= 0) { 82 if (result > 0) {
87 src += result; 83 src += result;
88 len -= result; 84 len -= result;
89 } else { 85 } else if (result == 0 || errno != EINTR) {
90 NaClLog(LOG_FATAL, 86 NaClLog(LOG_FATAL,
91 "TransportIPC::Write: Pipe closed from other process.\n"); 87 "TransportIPC::Write: Pipe closed from other process.\n");
92 } 88 }
93 } 89 }
94 return true; 90 return true;
95 } 91 }
96 92
97 // Return true if there is data to read. 93 // Return true if there is data to read.
98 virtual bool IsDataAvailable() { 94 virtual bool IsDataAvailable() {
99 CHECK(IsConnected()); 95 CHECK(IsConnected());
100 if (unconsumed_bytes_ > 0) return true; 96 if (unconsumed_bytes_ > 0) return true;
101
102 #if NACL_WINDOWS
103 DWORD available_bytes = 0;
104 // Return true if the pipe has data or there is an error.
105 if (PeekNamedPipe(handle_, NULL, 0, NULL, &available_bytes, NULL))
106 return available_bytes > 0;
107 else
108 return true;
109 #else
110 fd_set fds; 97 fd_set fds;
111 98
112 FD_ZERO(&fds); 99 FD_ZERO(&fds);
113 FD_SET(handle_, &fds); 100 FD_SET(handle_, &fds);
114 101
115 // We want a "non-blocking" check 102 // We want a "non-blocking" check
116 struct timeval timeout; 103 struct timeval timeout;
117 timeout.tv_sec = 0; 104 timeout.tv_sec = 0;
118 timeout.tv_usec = 0; 105 timeout.tv_usec = 0;
119 106
120 // Check if this file handle can select on read 107 // Check if this file handle can select on read
121 int cnt = select(handle_ + 1, &fds, 0, 0, &timeout); 108 int cnt = select(handle_ + 1, &fds, 0, 0, &timeout);
122 109
123 // If we are ready, or if there is an error. We return true 110 // If we are ready, or if there is an error. We return true
124 // on error, to let the next IO request fail. 111 // on error, to let the next IO request fail.
125 if (cnt != 0) return true; 112 if (cnt != 0) return true;
126 113
127 return false; 114 return false;
128 #endif
129 } 115 }
130 116
131 void WaitForDebugStubEvent(struct NaClApp *nap, 117 void WaitForDebugStubEvent(struct NaClApp *nap,
132 bool ignore_input_from_gdb) { 118 bool ignore_input_from_gdb) {
133 bool wait = true; 119 bool wait = true;
134 // If we are told to ignore messages from gdb, we will exit from this 120 // If we are told to ignore messages from gdb, we will exit from this
135 // function only if new data is sent by gdb. 121 // function only if new data is sent by gdb.
136 if ((unconsumed_bytes_ > 0 && !ignore_input_from_gdb) || 122 if ((unconsumed_bytes_ > 0 && !ignore_input_from_gdb) ||
137 nap->faulted_thread_count > 0) { 123 nap->faulted_thread_count > 0) {
138 // Clear faulted thread events to save debug stub loop iterations. 124 // Clear faulted thread events to save debug stub loop iterations.
139 wait = false; 125 wait = false;
140 } 126 }
141 127
142 #if NACL_WINDOWS
143 HANDLE handles[2];
144 handles[0] = nap->faulted_thread_event;
145 handles[1] = handle_;
146 int result = WaitForMultipleObjects(2, handles, FALSE,
147 wait ? INFINITE : 0);
148 if (result == WAIT_OBJECT_0 ||
149 result == WAIT_OBJECT_0 + 1 ||
150 result == WAIT_TIMEOUT)
151 return;
152 NaClLog(LOG_FATAL,
153 "TransportIPC::WaitForDebugStubEvent: Wait for events failed.\n");
154 #else
155 fd_set fds; 128 fd_set fds;
156 129
157 FD_ZERO(&fds); 130 FD_ZERO(&fds);
158 FD_SET(nap->faulted_thread_fd_read, &fds); 131 FD_SET(nap->faulted_thread_fd_read, &fds);
159 int max_fd = nap->faulted_thread_fd_read; 132 int max_fd = nap->faulted_thread_fd_read;
160 if (unconsumed_bytes_ < kBufSize) { 133 if (unconsumed_bytes_ < kBufSize) {
161 FD_SET(handle_, &fds); 134 FD_SET(handle_, &fds);
162 max_fd = std::max(max_fd, handle_); 135 max_fd = std::max(max_fd, handle_);
163 } 136 }
164 137
165 int ret; 138 int ret;
166 // We don't need sleep-polling on Linux now, 139 // We don't need sleep-polling on Linux now,
167 // so we set either zero or infinite timeout. 140 // so we set either zero or infinite timeout.
168 if (wait) { 141 if (wait) {
169 ret = select(max_fd + 1, &fds, NULL, NULL, NULL); 142 ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
170 } else { 143 } else {
171 struct timeval timeout; 144 struct timeval timeout;
172 timeout.tv_sec = 0; 145 timeout.tv_sec = 0;
173 timeout.tv_usec = 0; 146 timeout.tv_usec = 0;
174 ret = select(max_fd + 1, &fds, NULL, NULL, &timeout); 147 ret = select(max_fd + 1, &fds, NULL, NULL, &timeout);
175 } 148 }
176 if (ret < 0) { 149 if (ret < 0) {
177 NaClLog(LOG_FATAL, 150 NaClLog(LOG_FATAL,
178 "TransportIPC::WaitForDebugStubEvent: Wait for events failed.\n"); 151 "TransportIPC::WaitForDebugStubEvent: Failed to wait for "
152 "debug stub event.\n");
179 } 153 }
180 154
181 if (ret > 0) { 155 if (ret > 0) {
182 if (FD_ISSET(nap->faulted_thread_fd_read, &fds)) { 156 if (FD_ISSET(nap->faulted_thread_fd_read, &fds)) {
183 char buf[16]; 157 char buf[16];
184 if (read(nap->faulted_thread_fd_read, &buf, sizeof(buf)) < 0) { 158 if (read(nap->faulted_thread_fd_read, &buf, sizeof(buf)) < 0) {
185 NaClLog(LOG_FATAL, 159 NaClLog(LOG_FATAL,
186 "TransportIPC::WaitForDebugStubEvent: Failed to read from " 160 "TransportIPC::WaitForDebugStubEvent: Failed to read from "
187 "debug stub event pipe fd.\n"); 161 "debug stub event pipe fd.\n");
188 } 162 }
189 } 163 }
190 if (FD_ISSET(handle_, &fds)) 164 if (FD_ISSET(handle_, &fds))
191 FillBufferIfEmpty(); 165 FillBufferIfEmpty();
192 } 166 }
193 #endif
194 } 167 }
195 168
196 virtual void Disconnect() { 169 virtual void Disconnect() {
197 // If we are being marked as disconnected then we should also 170 // If we are being marked as disconnected then we should also
198 // receive the disconnect marker so the next connection is in 171 // receive the disconnect marker so the next connection is in
199 // a proper state. 172 // a proper state.
200 if (IsConnected()) { 173 if (IsConnected()) {
201 do { 174 do {
202 unconsumed_bytes_ = 0; 175 unconsumed_bytes_ = 0;
203 // FillBufferIfEmpty() returns false on disconnect or a 176 // FillBufferIfEmpty() returns false on disconnect or a
204 // Fatal error, and in both cases we want to exit the loop. 177 // Fatal error, and in both cases we want to exit the loop.
205 } while (FillBufferIfEmpty()); 178 } while (FillBufferIfEmpty());
206 } 179 }
207 180
208 // Throw away unused data. 181 // Throw away unused data.
209 unconsumed_bytes_ = 0; 182 unconsumed_bytes_ = 0;
210 } 183 }
211 184
212 // Block until we have new data on the pipe, new data means the 185 // Block until we have new data on the pipe, new data means the
213 // server socket across the pipe got a new connection. 186 // server socket across the pipe got a new connection.
214 virtual bool AcceptConnection() { 187 virtual bool AcceptConnection() {
215 CHECK(!IsConnected()); 188 CHECK(!IsConnected());
216 #if NACL_WINDOWS
217 if (WaitForSingleObject(handle_, INFINITE) == WAIT_OBJECT_0) {
218 // This marks ourself as connected.
219 bytes_to_read_ = 0;
220 return true;
221 }
222 NaClLog(LOG_FATAL,
223 "TransportIPC::WaitForDebugStubEvent: Wait for events failed.\n");
224 return false;
225 #else
226 fd_set fds; 189 fd_set fds;
227 190
228 FD_ZERO(&fds); 191 FD_ZERO(&fds);
229 FD_SET(handle_, &fds); 192 FD_SET(handle_, &fds);
230 193
231 // Check if this file handle can select on read 194 // Check if this file handle can select on read
232 int cnt = select(handle_ + 1, &fds, 0, 0, NULL); 195 int cnt = select(handle_ + 1, &fds, 0, 0, NULL);
233 196
234 // If we are ready, or if there is an error. We return true 197 // If we are ready, or if there is an error. We return true
235 // on error, to let the next IO request fail. 198 // on error, to let the next IO request fail.
236 if (cnt != 0) { 199 if (cnt != 0) {
237 // This marks ourself as connected. 200 // This marks ourself as connected.
238 bytes_to_read_ = 0; 201 bytes_to_read_ = 0;
239 return true; 202 return true;
240 } 203 }
241 204
242 return false; 205 return false;
243 #endif
244 } 206 }
245 207
246 private: 208 private:
247 // Returns whether we are in a connected state. This refers to the 209 // Returns whether we are in a connected state. This refers to the
248 // connection of the server across the pipe, if the pipe itself is 210 // connection of the server across the pipe, if the pipe itself is
249 // ever disconnected we will probably be crashing or exitting soon. 211 // ever disconnected we will probably be crashing or exitting soon.
250 bool IsConnected() { 212 bool IsConnected() {
251 return bytes_to_read_ != kServerSocketDisconnect; 213 return bytes_to_read_ != kServerSocketDisconnect;
252 } 214 }
253 215
(...skipping 28 matching lines...) Expand all
282 // We want to mark ourselves as disconnected on an error. 244 // We want to mark ourselves as disconnected on an error.
283 bytes_to_read_ = kServerSocketDisconnect; 245 bytes_to_read_ = kServerSocketDisconnect;
284 return false; 246 return false;
285 } 247 }
286 248
287 // If we got the disconnect flag mark it as such. 249 // If we got the disconnect flag mark it as such.
288 if (bytes_to_read_ == kServerSocketDisconnect) 250 if (bytes_to_read_ == kServerSocketDisconnect)
289 return false; 251 return false;
290 } 252 }
291 253
292 int result = ReadInternal(handle_, buf_.get() + unconsumed_bytes_, 254 int result = ::read(handle_, buf_.get() + unconsumed_bytes_,
293 std::min(bytes_to_read_, kBufSize)); 255 std::min(bytes_to_read_, kBufSize));
294 if (result >= 0) { 256 if (result > 0) {
295 unconsumed_bytes_ += result; 257 unconsumed_bytes_ += result;
296 bytes_to_read_ -= result; 258 bytes_to_read_ -= result;
297 } else { 259 } else if (result == 0 || errno != EINTR) {
298 NaClLog(LOG_FATAL, 260 NaClLog(LOG_FATAL,
299 "TransportIPC::FillBufferIfEmpty: " 261 "TransportIPC::FillBufferIfEmpty: "
300 "Pipe closed from other process.\n"); 262 "Pipe closed from other process.\n");
301 // We want to mark ourselves as disconnected on an error. 263 // We want to mark ourselves as disconnected on an error.
302 bytes_to_read_ = kServerSocketDisconnect; 264 bytes_to_read_ = kServerSocketDisconnect;
303 return false; 265 return false;
304 } 266 }
305 267
306 return true; 268 return true;
307 } 269 }
308 270
309 // Block until you read len bytes. Return false on error. 271 // Block until you read len bytes.
272 // Return false on EOF or error, but retries EINTR.
310 bool ReadNBytes(char *buf, uint32_t len) { 273 bool ReadNBytes(char *buf, uint32_t len) {
311 uint32_t bytes_read = 0; 274 uint32_t bytes_read = 0;
312 while (len > 0) { 275 while (len > 0) {
313 int result = ReadInternal(handle_, buf + bytes_read, len); 276 int result = ::read(handle_, buf + bytes_read, len);
314 if (result >= 0) { 277 if (result > 0) {
315 bytes_read += result; 278 bytes_read += result;
316 len -= result; 279 len -= result;
317 } else { 280 } else if (result == 0 || errno != EINTR) {
318 return false; 281 return false;
319 } 282 }
320 } 283 }
321 return true; 284 return true;
322 } 285 }
323 286
324 // Platform independant read. Returns number of bytes read or
325 // -1 on eof or error. Eof is treated as an error since the pipe
326 // should never be closed on the other end. On posix EINTR will
327 // return 0.
328 static int ReadInternal(NaClHandle handle, char *buf, int len) {
329 #if NACL_WINDOWS
330 DWORD bytes_read = 0;
331
332 if (!ReadFile(handle, buf, len, &bytes_read, NULL))
333 return -1;
334 else
335 return static_cast<int>(bytes_read);
336 #else
337 int result = ::read(handle, buf, len);
338 if (result > 0)
339 return result;
340 else if (result == 0 || errno != EINTR)
341 return -1;
342 else
343 return 0;
344 #endif
345 }
346
347 // Platform independant write. Returns number of bytes read or
348 // -1 on eof or error. Eof is treated as an error since the pipe
349 // should never be closed on the other end. On posix EINTR will
350 // return 0.
351 static int WriteInternal(NaClHandle handle, const char *buf, int len) {
352 #if NACL_WINDOWS
353 DWORD bytes_written = 0;
354
355 if (!WriteFile(handle, buf, len, &bytes_written, NULL))
356 return -1;
357 else
358 return static_cast<int>(bytes_written);
359 #else
360 int result = ::write(handle, buf, len);
361 if (result > 0)
362 return result;
363 else if (result == 0 || errno != EINTR)
364 return -1;
365 else
366 return 0;
367 #endif
368 }
369
370 static const int kServerSocketDisconnect = -1; 287 static const int kServerSocketDisconnect = -1;
371 static const int kBufSize = 4096; 288 static const int kBufSize = 4096;
372 nacl::scoped_array<char> buf_; 289 nacl::scoped_array<char> buf_;
373 290
374 // Number of bytes stored in internal buffer. 291 // Number of bytes stored in internal buffer.
375 int32_t unconsumed_bytes_; 292 int32_t unconsumed_bytes_;
376 293
377 // Number of bytes left in packet encoding from browser. 294 // Number of bytes left in packet encoding from browser.
378 int32_t bytes_to_read_; 295 int32_t bytes_to_read_;
379 NaClHandle handle_; 296 NaClHandle handle_;
380 }; 297 };
381 298
382 // The constant is passed by reference in some cases. So 299 // The constant is passed by reference in some cases. So
383 // under some optmizations or lack thereof it needs space. 300 // under some optmizations or lack thereof it needs space.
384 const int TransportIPC::kBufSize; 301 const int TransportIPC::kBufSize;
385 302
303 #endif
304
386 ITransport *CreateTransportIPC(NaClHandle fd) { 305 ITransport *CreateTransportIPC(NaClHandle fd) {
306 #if NACL_LINUX || NACL_OSX
387 return new TransportIPC(fd); 307 return new TransportIPC(fd);
308 #else
309 // TODO(leslieb): implement for windows.
310 return NULL;
311 #endif
388 } 312 }
389 313
390 } // namespace port 314 } // namespace port
OLDNEW
« no previous file with comments | « src/trusted/debug_stub/build.scons ('k') | src/trusted/debug_stub/transport_ipc_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698