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

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: sync 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
« no previous file with comments | « mojo/edk/system/child_broker_host.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <fcntl.h>
25 #include <sys/uio.h>
26
27 #include "mojo/edk/embedder/platform_channel_utils_posix.h"
28 #endif
29
21 namespace mojo { 30 namespace mojo {
22 namespace edk { 31 namespace edk {
23 32
24 namespace { 33 namespace {
25 #if defined(OS_WIN) 34 #if defined(OS_WIN)
26 static const int kDefaultReadBufferSize = 256; 35 static const int kDefaultReadBufferSize = 256;
27 #endif 36 #endif
28 } 37 }
29 38
30 ChildBrokerHost::ChildBrokerHost(base::ProcessHandle child_process, 39 ChildBrokerHost::ChildBrokerHost(base::ProcessHandle child_process,
31 ScopedPlatformHandle pipe) 40 ScopedPlatformHandle pipe)
32 : process_id_(base::GetProcId(child_process)), child_channel_(nullptr) { 41 : process_id_(base::GetProcId(child_process)),
33 ScopedPlatformHandle parent_async_channel_handle; 42 child_channel_(nullptr),
34 #if defined(OS_POSIX) 43 num_bytes_read_(0) {
35 parent_async_channel_handle = std::move(pipe); 44 // First set up the synchronous pipe.
36 #else 45 sync_channel_ = std::move(pipe);
46
47 // See comment in ChildBroker::SetChildBrokerHostHandle. Summary is we need
48 // two pipes, so send the second one over the first one.
49 PlatformChannelPair parent_pipe;
50
51 ScopedPlatformHandle parent_async_channel_handle =
52 parent_pipe.PassServerHandle();
53
54 num_bytes_read_ = 0;
55
56 // Send over the async pipe.
57 #if defined(OS_WIN)
37 DuplicateHandle(GetCurrentProcess(), child_process, 58 DuplicateHandle(GetCurrentProcess(), child_process,
38 GetCurrentProcess(), &child_process, 59 GetCurrentProcess(), &child_process,
39 0, FALSE, DUPLICATE_SAME_ACCESS); 60 0, FALSE, DUPLICATE_SAME_ACCESS);
40 child_process_ = base::Process(child_process); 61 child_process_ = base::Process(child_process);
41 sync_channel_ = pipe.Pass(); 62
42 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); 63 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped));
43 read_context_.handler = this; 64 read_context_.handler = this;
44 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); 65 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped));
45 write_context_.handler = this; 66 write_context_.handler = this;
46 read_data_.resize(kDefaultReadBufferSize); 67 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 68
54 HANDLE duplicated_child_handle = 69 HANDLE duplicated_child_handle =
55 DuplicateToChild(parent_pipe.PassClientHandle().release().handle); 70 DuplicateToChild(parent_pipe.PassClientHandle().release().handle);
56 BOOL rv = WriteFile(sync_channel_.get().handle, 71 BOOL rv = WriteFile(sync_channel_.get().handle,
57 &duplicated_child_handle, sizeof(duplicated_child_handle), 72 &duplicated_child_handle, sizeof(duplicated_child_handle),
58 NULL, &write_context_.overlapped); 73 NULL, &write_context_.overlapped);
59 DCHECK(rv || GetLastError() == ERROR_IO_PENDING); 74 DCHECK(rv || GetLastError() == ERROR_IO_PENDING);
75 #else
76 // Send just one null byte.
77 struct iovec iov = {const_cast<char*>(""), 1};
78 PlatformHandle child_handle = parent_pipe.PassClientHandle().release();
79 ssize_t result = PlatformChannelSendmsgWithHandles(sync_channel_.get(), &iov,
80 1, &child_handle, 1);
81 CHECK_NE(-1, result);
60 #endif 82 #endif
61 83
62 internal::g_io_thread_task_runner->PostTask( 84 internal::g_io_thread_task_runner->PostTask(
63 FROM_HERE, 85 FROM_HERE,
64 base::Bind(&ChildBrokerHost::InitOnIO, base::Unretained(this), 86 base::Bind(&ChildBrokerHost::InitOnIO, base::Unretained(this),
65 base::Passed(&parent_async_channel_handle))); 87 base::Passed(&parent_async_channel_handle)));
66 } 88 }
67 89
68 base::ProcessId ChildBrokerHost::GetProcessId() { 90 base::ProcessId ChildBrokerHost::GetProcessId() {
69 return process_id_; 91 return process_id_;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 156
135 BrokerState::GetInstance()->ChildBrokerHostCreated(this); 157 BrokerState::GetInstance()->ChildBrokerHostCreated(this);
136 158
137 #if defined(OS_WIN) 159 #if defined(OS_WIN)
138 // Call this after RoutedRawChannel calls its RawChannel::Init because this 160 // Call this after RoutedRawChannel calls its RawChannel::Init because this
139 // call could cause us to get notified that the child has gone away and to 161 // call could cause us to get notified that the child has gone away and to
140 // delete this class and shut down child_channel_ before Init() has run. 162 // delete this class and shut down child_channel_ before Init() has run.
141 base::MessageLoopForIO::current()->RegisterIOHandler( 163 base::MessageLoopForIO::current()->RegisterIOHandler(
142 sync_channel_.get().handle, this); 164 sync_channel_.get().handle, this);
143 BeginRead(); 165 BeginRead();
166 #else
167 base::MessageLoopForIO::current()->WatchFileDescriptor(
168 sync_channel_.get().handle, true, base::MessageLoopForIO::WATCH_READ,
169 &fd_controller_, this);
170 TryReadAndWriteHandles();
144 #endif 171 #endif
145 } 172 }
146 173
147 void ChildBrokerHost::OnReadMessage( 174 void ChildBrokerHost::OnReadMessage(
148 const MessageInTransit::View& message_view, 175 const MessageInTransit::View& message_view,
149 ScopedPlatformHandleVectorPtr platform_handles) { 176 ScopedPlatformHandleVectorPtr platform_handles) {
150 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); 177 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
151 CHECK(!platform_handles); 178 CHECK(!platform_handles);
152 if (message_view.num_bytes() != 179 if (message_view.num_bytes() !=
153 static_cast<uint32_t>(sizeof(ConnectMessagePipeMessage))) { 180 static_cast<uint32_t>(sizeof(ConnectMessagePipeMessage))) {
(...skipping 18 matching lines...) Expand all
172 } 199 }
173 } 200 }
174 201
175 void ChildBrokerHost::OnError(Error error) { 202 void ChildBrokerHost::OnError(Error error) {
176 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); 203 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
177 child_channel_->RemoveRoute(kBrokerRouteId); 204 child_channel_->RemoveRoute(kBrokerRouteId);
178 child_channel_ = nullptr; 205 child_channel_ = nullptr;
179 } 206 }
180 207
181 void ChildBrokerHost::ChannelDestructed(RoutedRawChannel* channel) { 208 void ChildBrokerHost::ChannelDestructed(RoutedRawChannel* channel) {
182 // On Windows, we have two pipes to the child process. It's easier to wait 209 // We have two pipes to the child process. It's easier to wait
183 // until we get the error from the pipe that is used for synchronous I/O. 210 // until we get the error from the pipe that is used for synchronous I/O.
184 #if !defined(OS_WIN)
185 delete this;
186 #endif
187 } 211 }
188 212
189 #if defined(OS_WIN) 213 #if defined(OS_WIN)
190 void ChildBrokerHost::BeginRead() { 214 void ChildBrokerHost::BeginRead() {
191 BOOL rv = ReadFile(sync_channel_.get().handle, 215 BOOL rv = ReadFile(sync_channel_.get().handle,
192 &read_data_[num_bytes_read_], 216 &read_data_[num_bytes_read_],
193 static_cast<int>(read_data_.size() - num_bytes_read_), 217 static_cast<int>(read_data_.size() - num_bytes_read_),
194 nullptr, &read_context_.overlapped); 218 nullptr, &read_context_.overlapped);
195 if (rv || GetLastError() == ERROR_IO_PENDING) 219 if (rv || GetLastError() == ERROR_IO_PENDING)
196 return; 220 return;
(...skipping 21 matching lines...) Expand all
218 return; 242 return;
219 } 243 }
220 244
221 if (context == &write_context_) { 245 if (context == &write_context_) {
222 write_data_.clear(); 246 write_data_.clear();
223 return; 247 return;
224 } 248 }
225 249
226 num_bytes_read_ += bytes_transferred; 250 num_bytes_read_ += bytes_transferred;
227 CHECK_GE(num_bytes_read_, sizeof(uint32_t)); 251 CHECK_GE(num_bytes_read_, sizeof(uint32_t));
228 BrokerMessage* message = reinterpret_cast<BrokerMessage*>(&read_data_[0]); 252 BrokerMessage* message = reinterpret_cast<BrokerMessage*>(read_data_.data());
229 if (num_bytes_read_ < message->size) { 253 if (num_bytes_read_ < message->size) {
230 read_data_.resize(message->size); 254 read_data_.resize(message->size);
231 BeginRead(); 255 BeginRead();
232 return; 256 return;
233 } 257 }
234 258
235 // This should never fire because we only get new requests from a child 259 // This should never fire because we only get new requests from a child
236 // process after it has read all the previous data we wrote. 260 // process after it has read all the previous data we wrote.
237 if (!write_data_.empty()) { 261 if (!write_data_.empty()) {
238 NOTREACHED() << "ChildBrokerHost shouldn't have data to write when it gets " 262 NOTREACHED() << "ChildBrokerHost shouldn't have data to write when it gets "
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 } 340 }
317 341
318 HANDLE ChildBrokerHost::DuplicateFromChild(HANDLE handle) { 342 HANDLE ChildBrokerHost::DuplicateFromChild(HANDLE handle) {
319 HANDLE rv = INVALID_HANDLE_VALUE; 343 HANDLE rv = INVALID_HANDLE_VALUE;
320 BOOL result = DuplicateHandle(child_process_.Handle(), handle, 344 BOOL result = DuplicateHandle(child_process_.Handle(), handle,
321 base::GetCurrentProcessHandle(), &rv, 0, FALSE, 345 base::GetCurrentProcessHandle(), &rv, 0, FALSE,
322 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 346 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
323 DCHECK(result); 347 DCHECK(result);
324 return rv; 348 return rv;
325 } 349 }
350 #else
351 void ChildBrokerHost::TryReadAndWriteHandles() {
352 // Message sizes are constant on POSIX currently. Further, the child process
353 // only writes one message before it gets a response.
354 read_data_.resize(sizeof(BrokerMessage));
355
356 std::deque<PlatformHandle> dummy;
357 ssize_t bytes_read = PlatformChannelRecvmsg(
358 sync_channel_.get(), &read_data_[num_bytes_read_],
359 static_cast<int>(read_data_.size() - num_bytes_read_), &dummy);
360 DCHECK(dummy.empty());
361
362 // We call TryReadAndWriteHandles when we are first initialized so this could
363 // fail with EAGAIN or EWOULDBLOCK.
364 if (bytes_read == 0 ||
365 (bytes_read == -1 && errno != EAGAIN && errno != EWOULDBLOCK)) {
366 delete this;
367 return;
368 }
369
370 if (bytes_read == -1)
371 return;
372
373 num_bytes_read_ += bytes_read;
374
375 // We don't know how big the message is yet.
376 if (num_bytes_read_ < sizeof(uint32_t))
377 return;
378
379 BrokerMessage* message = reinterpret_cast<BrokerMessage*>(read_data_.data());
380 // Message not fully read yet.
381 if (num_bytes_read_ < message->size) {
382 DCHECK_LE(message->size, sizeof(BrokerMessage));
383 return;
384 }
385
386 // Should only get one message.
387 DCHECK_EQ(num_bytes_read_, message->size);
388
389 PlatformHandle handle;
390 if (message->id == CREATE_SHARED_BUFFER) {
391 scoped_refptr<PlatformSharedBuffer> shared_buffer =
392 internal::g_platform_support->CreateSharedBuffer(
393 message->shared_buffer_size);
394 if (shared_buffer)
395 handle = shared_buffer->PassPlatformHandle().release();
396 else
397 LOG(ERROR) << "ChildBrokerHost failed to create shared buffer of size "
398 << message->shared_buffer_size;
399 } else {
400 NOTREACHED() << "Unknown command. Stopping reading.";
401 delete this;
402 return;
403 }
404
405 num_bytes_read_ = 0;
406 read_data_.clear();
407
408 // Send just one null byte. Also send back a null platform handle if we
409 // couldn't create the shared buffer.
410 struct iovec iov = {const_cast<char*>(""), 1};
411 ssize_t result = PlatformChannelSendmsgWithHandles(sync_channel_.get(), &iov,
412 1, &handle, 1);
413 if (result == -1) {
414 PLOG(ERROR) << "ChildBrokerHost could not write to peer";
415 delete this;
416 }
417 }
418
419 void ChildBrokerHost::OnFileCanReadWithoutBlocking(int fd) {
420 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
421 if (fd != sync_channel_.get().handle) {
422 NOTREACHED() << "ChildBrokerHost shouldn't get notifications about file "
423 "descriptors other than sync_channel_'s";
424 delete this;
425 return;
426 }
427
428 TryReadAndWriteHandles();
429 }
430
431 void ChildBrokerHost::OnFileCanWriteWithoutBlocking(int fd) {}
326 #endif 432 #endif
327 433
328 } // namespace edk 434 } // namespace edk
329 } // namespace mojo 435 } // namespace mojo
OLDNEW
« no previous file with comments | « 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