OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/edk/system/channel.h" | 5 #include "mojo/edk/system/channel.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <sys/uio.h> | 8 #include <sys/uio.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 | 59 |
60 size_t data_offset() const { return offset_; } | 60 size_t data_offset() const { return offset_; } |
61 void advance_data_offset(size_t num_bytes) { | 61 void advance_data_offset(size_t num_bytes) { |
62 DCHECK_GT(message_->data_num_bytes(), offset_ + num_bytes); | 62 DCHECK_GT(message_->data_num_bytes(), offset_ + num_bytes); |
63 offset_ += num_bytes; | 63 offset_ += num_bytes; |
64 } | 64 } |
65 | 65 |
66 ScopedPlatformHandleVectorPtr TakeHandles() { return std::move(handles_); } | 66 ScopedPlatformHandleVectorPtr TakeHandles() { return std::move(handles_); } |
67 Channel::MessagePtr TakeMessage() { return std::move(message_); } | 67 Channel::MessagePtr TakeMessage() { return std::move(message_); } |
68 | 68 |
| 69 void SetHandles(ScopedPlatformHandleVectorPtr handles) { |
| 70 handles_ = std::move(handles); |
| 71 } |
| 72 |
69 private: | 73 private: |
70 Channel::MessagePtr message_; | 74 Channel::MessagePtr message_; |
71 size_t offset_; | 75 size_t offset_; |
72 ScopedPlatformHandleVectorPtr handles_; | 76 ScopedPlatformHandleVectorPtr handles_; |
73 | 77 |
74 DISALLOW_COPY_AND_ASSIGN(MessageView); | 78 DISALLOW_COPY_AND_ASSIGN(MessageView); |
75 }; | 79 }; |
76 | 80 |
77 class ChannelPosix : public Channel, | 81 class ChannelPosix : public Channel, |
78 public base::MessageLoop::DestructionObserver, | 82 public base::MessageLoop::DestructionObserver, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 ssize_t result; | 274 ssize_t result; |
271 ScopedPlatformHandleVectorPtr handles = message_view.TakeHandles(); | 275 ScopedPlatformHandleVectorPtr handles = message_view.TakeHandles(); |
272 if (handles && handles->size()) { | 276 if (handles && handles->size()) { |
273 iovec iov = { | 277 iovec iov = { |
274 const_cast<void*>(message_view.data()), | 278 const_cast<void*>(message_view.data()), |
275 message_view.data_num_bytes() | 279 message_view.data_num_bytes() |
276 }; | 280 }; |
277 // TODO: Handle lots of handles. | 281 // TODO: Handle lots of handles. |
278 result = PlatformChannelSendmsgWithHandles( | 282 result = PlatformChannelSendmsgWithHandles( |
279 handle_.get(), &iov, 1, handles->data(), handles->size()); | 283 handle_.get(), &iov, 1, handles->data(), handles->size()); |
| 284 if (result >= 0) { |
280 #if defined(OS_MACOSX) | 285 #if defined(OS_MACOSX) |
281 // There is a bug on OSX which makes it dangerous to close | 286 // There is a bug on OSX which makes it dangerous to close |
282 // a file descriptor while it is in transit. So instead we | 287 // a file descriptor while it is in transit. So instead we |
283 // store the file descriptor in a set and send a message to | 288 // store the file descriptor in a set and send a message to |
284 // the recipient, which is queued AFTER the message that | 289 // the recipient, which is queued AFTER the message that |
285 // sent the FD. The recipient will reply to the message, | 290 // sent the FD. The recipient will reply to the message, |
286 // letting us know that it is now safe to close the file | 291 // letting us know that it is now safe to close the file |
287 // descriptor. For more information, see: | 292 // descriptor. For more information, see: |
288 // http://crbug.com/298276 | 293 // http://crbug.com/298276 |
289 std::vector<int> fds; | 294 std::vector<int> fds; |
290 for (auto& handle : *handles) | |
291 fds.push_back(handle.handle); | |
292 { | |
293 base::AutoLock l(handles_to_close_lock_); | |
294 for (auto& handle : *handles) | 295 for (auto& handle : *handles) |
295 handles_to_close_->push_back(handle); | 296 fds.push_back(handle.handle); |
| 297 { |
| 298 base::AutoLock l(handles_to_close_lock_); |
| 299 for (auto& handle : *handles) |
| 300 handles_to_close_->push_back(handle); |
| 301 } |
| 302 MessagePtr fds_message( |
| 303 new Channel::Message(sizeof(fds[0]) * fds.size(), 0, |
| 304 Message::Header::MessageType::HANDLES_SENT)); |
| 305 memcpy(fds_message->mutable_payload(), fds.data(), |
| 306 sizeof(fds[0]) * fds.size()); |
| 307 outgoing_messages_.emplace_back(std::move(fds_message), 0); |
| 308 handles->clear(); |
| 309 #else |
| 310 handles.reset(); |
| 311 #endif // defined(OS_MACOSX) |
296 } | 312 } |
297 MessagePtr fds_message( | |
298 new Channel::Message(sizeof(fds[0]) * fds.size(), 0, | |
299 Message::Header::MessageType::HANDLES_SENT)); | |
300 memcpy(fds_message->mutable_payload(), fds.data(), | |
301 sizeof(fds[0]) * fds.size()); | |
302 outgoing_messages_.emplace_back(std::move(fds_message), 0); | |
303 handles->clear(); | |
304 #else | |
305 handles.reset(); | |
306 #endif // defined(OS_MACOSX) | |
307 } else { | 313 } else { |
308 result = PlatformChannelWrite(handle_.get(), message_view.data(), | 314 result = PlatformChannelWrite(handle_.get(), message_view.data(), |
309 message_view.data_num_bytes()); | 315 message_view.data_num_bytes()); |
310 } | 316 } |
311 | 317 |
312 if (result < 0) { | 318 if (result < 0) { |
313 if (errno != EAGAIN && errno != EWOULDBLOCK) | 319 if (errno != EAGAIN && errno != EWOULDBLOCK) |
314 return false; | 320 return false; |
| 321 message_view.SetHandles(std::move(handles)); |
315 outgoing_messages_.emplace_front(std::move(message_view)); | 322 outgoing_messages_.emplace_front(std::move(message_view)); |
316 WaitForWriteOnIOThreadNoLock(); | 323 WaitForWriteOnIOThreadNoLock(); |
317 return true; | 324 return true; |
318 } | 325 } |
319 | 326 |
320 bytes_written = static_cast<size_t>(result); | 327 bytes_written = static_cast<size_t>(result); |
321 } while (bytes_written < message_view.data_num_bytes()); | 328 } while (bytes_written < message_view.data_num_bytes()); |
322 | 329 |
323 return FlushOutgoingMessagesNoLock(); | 330 return FlushOutgoingMessagesNoLock(); |
324 } | 331 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 // static | 448 // static |
442 scoped_refptr<Channel> Channel::Create( | 449 scoped_refptr<Channel> Channel::Create( |
443 Delegate* delegate, | 450 Delegate* delegate, |
444 ScopedPlatformHandle platform_handle, | 451 ScopedPlatformHandle platform_handle, |
445 scoped_refptr<base::TaskRunner> io_task_runner) { | 452 scoped_refptr<base::TaskRunner> io_task_runner) { |
446 return new ChannelPosix(delegate, std::move(platform_handle), io_task_runner); | 453 return new ChannelPosix(delegate, std::move(platform_handle), io_task_runner); |
447 } | 454 } |
448 | 455 |
449 } // namespace edk | 456 } // namespace edk |
450 } // namespace mojo | 457 } // namespace mojo |
OLD | NEW |