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

Side by Side Diff: mojo/edk/system/child_broker_host.cc

Issue 1555273002: [mojo] Add CreateSharedBuffer method to Broker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/child_broker_host.h" 5 #include "mojo/edk/system/child_broker_host.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "mojo/edk/embedder/embedder_internal.h" 13 #include "mojo/edk/embedder/embedder_internal.h"
14 #include "mojo/edk/embedder/platform_channel_pair.h" 14 #include "mojo/edk/embedder/platform_channel_pair.h"
15 #include "mojo/edk/embedder/platform_shared_buffer.h"
16 #include "mojo/edk/embedder/platform_support.h"
15 #include "mojo/edk/system/broker_messages.h" 17 #include "mojo/edk/system/broker_messages.h"
16 #include "mojo/edk/system/broker_state.h" 18 #include "mojo/edk/system/broker_state.h"
17 #include "mojo/edk/system/configuration.h" 19 #include "mojo/edk/system/configuration.h"
18 #include "mojo/edk/system/core.h" 20 #include "mojo/edk/system/core.h"
19 #include "mojo/edk/system/platform_handle_dispatcher.h" 21 #include "mojo/edk/system/platform_handle_dispatcher.h"
20 22
23 #if defined(OS_POSIX)
24 #include <sys/uio.h>
25
26 #include "mojo/edk/embedder/platform_channel_utils_posix.h"
27 #endif
28
21 namespace mojo { 29 namespace mojo {
22 namespace edk { 30 namespace edk {
23 31
24 namespace { 32 namespace {
25 #if defined(OS_WIN) 33 #if defined(OS_WIN)
26 static const int kDefaultReadBufferSize = 256; 34 static const int kDefaultReadBufferSize = 256;
27 #endif 35 #endif
28 } 36 }
29 37
30 ChildBrokerHost::ChildBrokerHost(base::ProcessHandle child_process, 38 ChildBrokerHost::ChildBrokerHost(base::ProcessHandle child_process,
31 ScopedPlatformHandle pipe) 39 ScopedPlatformHandle pipe)
32 : process_id_(base::GetProcId(child_process)), child_channel_(nullptr) { 40 : process_id_(base::GetProcId(child_process)),
33 ScopedPlatformHandle parent_async_channel_handle; 41 child_channel_(nullptr),
34 #if defined(OS_POSIX) 42 num_bytes_read_(0) {
35 parent_async_channel_handle = std::move(pipe); 43 // First set up the synchronous pipe.
36 #else 44 sync_channel_ = std::move(pipe);
45
46 // See comment in ChildBroker::SetChildBrokerHostHandle. Summary is we need
47 // two pipes, so send the second one over the first one.
48 PlatformChannelPair parent_pipe;
49
50 ScopedPlatformHandle parent_async_channel_handle =
51 parent_pipe.PassServerHandle();
52
53 num_bytes_read_ = 0;
54
55 // Send over the async pipe.
56 #if defined(OS_WIN)
37 DuplicateHandle(GetCurrentProcess(), child_process, 57 DuplicateHandle(GetCurrentProcess(), child_process,
38 GetCurrentProcess(), &child_process, 58 GetCurrentProcess(), &child_process,
39 0, FALSE, DUPLICATE_SAME_ACCESS); 59 0, FALSE, DUPLICATE_SAME_ACCESS);
40 child_process_ = base::Process(child_process); 60 child_process_ = base::Process(child_process);
41 sync_channel_ = pipe.Pass(); 61
42 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); 62 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
43 read_context_.handler = this; 63 read_context_.handler = this;
44 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); 64 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped));
45 write_context_.handler = this; 65 write_context_.handler = this;
46 read_data_.resize(kDefaultReadBufferSize); 66 read_data_.resize(kDefaultReadBufferSize);
47 num_bytes_read_ = 0;
48
49 // See comment in ChildBroker::SetChildBrokerHostHandle. Summary is we need
50 // two pipes on Windows, so send the second one over the first one.
51 PlatformChannelPair parent_pipe;
52 parent_async_channel_handle = parent_pipe.PassServerHandle();
53 67
54 HANDLE duplicated_child_handle = 68 HANDLE duplicated_child_handle =
55 DuplicateToChild(parent_pipe.PassClientHandle().release().handle); 69 DuplicateToChild(parent_pipe.PassClientHandle().release().handle);
56 BOOL rv = WriteFile(sync_channel_.get().handle, 70 BOOL rv = WriteFile(sync_channel_.get().handle,
57 &duplicated_child_handle, sizeof(duplicated_child_handle), 71 &duplicated_child_handle, sizeof(duplicated_child_handle),
58 NULL, &write_context_.overlapped); 72 NULL, &write_context_.overlapped);
59 DCHECK(rv || GetLastError() == ERROR_IO_PENDING); 73 DCHECK(rv || GetLastError() == ERROR_IO_PENDING);
74 #else
75 // Send just one null byte.
76 struct iovec iov = {const_cast<char*>(""), 1};
77 PlatformHandle child_handle = parent_pipe.PassClientHandle().release();
78 ssize_t result = PlatformChannelSendmsgWithHandles(sync_channel_.get(), &iov,
79 1, &child_handle, 1);
80 CHECK_NE(-1, result);
60 #endif 81 #endif
61 82
62 internal::g_io_thread_task_runner->PostTask( 83 internal::g_io_thread_task_runner->PostTask(
63 FROM_HERE, 84 FROM_HERE,
64 base::Bind(&ChildBrokerHost::InitOnIO, base::Unretained(this), 85 base::Bind(&ChildBrokerHost::InitOnIO, base::Unretained(this),
65 base::Passed(&parent_async_channel_handle))); 86 base::Passed(&parent_async_channel_handle)));
66 } 87 }
67 88
68 base::ProcessId ChildBrokerHost::GetProcessId() { 89 base::ProcessId ChildBrokerHost::GetProcessId() {
69 return process_id_; 90 return process_id_;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 142
122 BrokerState::GetInstance()->ChildBrokerHostCreated(this); 143 BrokerState::GetInstance()->ChildBrokerHostCreated(this);
123 144
124 #if defined(OS_WIN) 145 #if defined(OS_WIN)
125 // Call this after RoutedRawChannel calls its RawChannel::Init because this 146 // Call this after RoutedRawChannel calls its RawChannel::Init because this
126 // call could cause us to get notified that the child has gone away and to 147 // call could cause us to get notified that the child has gone away and to
127 // delete this class and shut down child_channel_ before Init() has run. 148 // delete this class and shut down child_channel_ before Init() has run.
128 base::MessageLoopForIO::current()->RegisterIOHandler( 149 base::MessageLoopForIO::current()->RegisterIOHandler(
129 sync_channel_.get().handle, this); 150 sync_channel_.get().handle, this);
130 BeginRead(); 151 BeginRead();
152 #else
153 base::MessageLoopForIO::current()->WatchFileDescriptor(
154 sync_channel_.get().handle, true, base::MessageLoopForIO::WATCH_READ,
155 &fd_controller_, this);
156 DoRead();
131 #endif 157 #endif
132 } 158 }
133 159
134 void ChildBrokerHost::OnReadMessage( 160 void ChildBrokerHost::OnReadMessage(
135 const MessageInTransit::View& message_view, 161 const MessageInTransit::View& message_view,
136 ScopedPlatformHandleVectorPtr platform_handles) { 162 ScopedPlatformHandleVectorPtr platform_handles) {
137 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); 163 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
138 CHECK(!platform_handles); 164 CHECK(!platform_handles);
139 if (message_view.num_bytes() != 165 if (message_view.num_bytes() !=
140 static_cast<uint32_t>(sizeof(ConnectMessagePipeMessage))) { 166 static_cast<uint32_t>(sizeof(ConnectMessagePipeMessage))) {
(...skipping 18 matching lines...) Expand all
159 } 185 }
160 } 186 }
161 187
162 void ChildBrokerHost::OnError(Error error) { 188 void ChildBrokerHost::OnError(Error error) {
163 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); 189 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
164 child_channel_->RemoveRoute(kBrokerRouteId); 190 child_channel_->RemoveRoute(kBrokerRouteId);
165 child_channel_ = nullptr; 191 child_channel_ = nullptr;
166 } 192 }
167 193
168 void ChildBrokerHost::ChannelDestructed(RoutedRawChannel* channel) { 194 void ChildBrokerHost::ChannelDestructed(RoutedRawChannel* channel) {
169 // On Windows, we have two pipes to the child process. It's easier to wait 195 // We have two pipes to the child process. It's easier to wait
170 // until we get the error from the pipe that is used for synchronous I/O. 196 // until we get the error from the pipe that is used for synchronous I/O.
171 #if !defined(OS_WIN)
172 delete this;
173 #endif
174 } 197 }
175 198
176 #if defined(OS_WIN) 199 #if defined(OS_WIN)
177 void ChildBrokerHost::BeginRead() { 200 void ChildBrokerHost::BeginRead() {
178 BOOL rv = ReadFile(sync_channel_.get().handle, 201 BOOL rv = ReadFile(sync_channel_.get().handle,
179 &read_data_[num_bytes_read_], 202 &read_data_[num_bytes_read_],
180 static_cast<int>(read_data_.size() - num_bytes_read_), 203 static_cast<int>(read_data_.size() - num_bytes_read_),
181 nullptr, &read_context_.overlapped); 204 nullptr, &read_context_.overlapped);
182 if (rv || GetLastError() == ERROR_IO_PENDING) 205 if (rv || GetLastError() == ERROR_IO_PENDING)
183 return; 206 return;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 } 326 }
304 327
305 HANDLE ChildBrokerHost::DuplicateFromChild(HANDLE handle) { 328 HANDLE ChildBrokerHost::DuplicateFromChild(HANDLE handle) {
306 HANDLE rv = INVALID_HANDLE_VALUE; 329 HANDLE rv = INVALID_HANDLE_VALUE;
307 BOOL result = DuplicateHandle(child_process_.Handle(), handle, 330 BOOL result = DuplicateHandle(child_process_.Handle(), handle,
308 base::GetCurrentProcessHandle(), &rv, 0, FALSE, 331 base::GetCurrentProcessHandle(), &rv, 0, FALSE,
309 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 332 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
310 DCHECK(result); 333 DCHECK(result);
311 return rv; 334 return rv;
312 } 335 }
336 #else
337 void ChildBrokerHost::DoRead() {
338 // Grab as many messages as we can before we would start blocking.
339 while (1) {
340 // Try to at least read the size of the message.
341 if (read_data_.size() < sizeof(uint32_t))
342 read_data_.resize(sizeof(uint32_t));
343 DCHECK_LT(num_bytes_read_, read_data_.size());
344
345 std::deque<PlatformHandle> dummy;
346 ssize_t bytes_read = PlatformChannelRecvmsg(
347 sync_channel_.get(), &read_data_[num_bytes_read_],
348 static_cast<int>(read_data_.size() - num_bytes_read_), &dummy);
349 DCHECK(dummy.empty());
350
351 // Connection closed.
352 if (bytes_read == 0 ||
353 (bytes_read == -1 && errno != EAGAIN && errno != EWOULDBLOCK)) {
354 delete this;
355 return;
356 }
357
358 // No more data.
359 if (bytes_read == -1)
360 break;
361
362 num_bytes_read_ += bytes_read;
363
364 // We don't know how big the message is yet.
365 if (num_bytes_read_ < sizeof(uint32_t))
366 continue;
367
368 BrokerMessage* message = reinterpret_cast<BrokerMessage*>(&read_data_[0]);
Anand Mistry (off Chromium) 2016/01/07 04:36:33 read_data_.data()
Eliot Courtney 2016/01/07 05:01:30 Done.
369
370 // Message not done yet.
371 if (num_bytes_read_ < message->size) {
372 read_data_.resize(message->size);
373 continue;
374 }
375
376 if (num_bytes_read_ >= message->size) {
377 if (message->id == CREATE_SHARED_BUFFER) {
378 scoped_refptr<PlatformSharedBuffer> shared_buffer =
379 internal::g_platform_support->CreateSharedBuffer(
380 message->num_bytes);
381 if (shared_buffer) {
382 write_handles_.push_back(
383 shared_buffer->PassPlatformHandle().release());
384 } else {
385 LOG(ERROR)
386 << "ChildBrokerHost failed to create shared buffer of size "
387 << message->num_bytes;
388 write_handles_.emplace_back();
389 }
390
391 } else {
392 NOTREACHED() << "Unknown command. Stopping reading.";
393 delete this;
394 return;
395 }
396
397 num_bytes_read_ -= message->size;
398 }
399 }
400
401 DoWrite();
402 }
403
404 void ChildBrokerHost::DoWrite() {
405 while (!write_handles_.empty()) {
406 // Send just one null byte.
407 struct iovec iov = {const_cast<char*>(""), 1};
408 PlatformHandle handle = write_handles_.front();
409 ssize_t result = PlatformChannelSendmsgWithHandles(sync_channel_.get(),
410 &iov, 1, &handle, 1);
411 if (result == -1)
412 break;
413 write_handles_.pop_front();
414 }
415 }
416
417 void ChildBrokerHost::OnFileCanReadWithoutBlocking(int fd) {
418 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
419 if (fd != sync_channel_.get().handle) {
420 NOTREACHED() << "ChildBrokerHost shouldn't get notifications about file "
421 "descriptors other than sync_channel_'s";
422 delete this;
423 return;
424 }
425
426 DoRead();
427 }
428
429 void ChildBrokerHost::OnFileCanWriteWithoutBlocking(int fd) {}
313 #endif 430 #endif
314 431
315 } // namespace edk 432 } // namespace edk
316 } // namespace mojo 433 } // namespace mojo
OLDNEW
« mojo/edk/system/child_broker.cc ('K') | « mojo/edk/system/child_broker_host.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698