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

Unified Diff: mojo/edk/system/child_broker.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, 12 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 side-by-side diff with in-line comments
Download patch
Index: mojo/edk/system/child_broker.cc
diff --git a/mojo/edk/system/child_broker.cc b/mojo/edk/system/child_broker.cc
index 6903c8204dbd23b393729c8e859407609dc983db..a9d1e75a0c16efa322e330f1ff88576920f5e5d6 100644
--- a/mojo/edk/system/child_broker.cc
+++ b/mojo/edk/system/child_broker.cc
@@ -13,9 +13,15 @@
#include "base/logging.h"
#include "mojo/edk/embedder/embedder_internal.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/embedder/platform_support.h"
#include "mojo/edk/system/broker_messages.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
+#if defined(OS_POSIX)
+#include "mojo/edk/embedder/platform_channel_utils_posix.h"
+#endif
+
namespace mojo {
namespace edk {
@@ -26,24 +32,30 @@ ChildBroker* ChildBroker::GetInstance() {
void ChildBroker::SetChildBrokerHostHandle(ScopedPlatformHandle handle) {
ScopedPlatformHandle parent_async_channel_handle;
+ parent_sync_channel_ = std::move(handle);
+
+// We have two pipes to the parent. The first is for the token
+// exchange for creating and passing handles on Windows, and creating shared
+// buffers on POSIX, since the child needs the parent's help if it is
+// sandboxed. The second is used for multiplexing related messages. We
+// send the second over the first.
#if defined(OS_POSIX)
- parent_async_channel_handle = std::move(handle);
+ std::deque<PlatformHandle> received_handles;
+ char buf[1];
+ ssize_t result = PlatformChannelRecvmsg(parent_sync_channel_.get(), buf, 1,
Eliot Courtney 2016/01/05 04:45:47 Does this need to be queried in a loop since it wo
jam 2016/01/06 02:58:16 ReadFile below specifies the number of bytes to re
Eliot Courtney 2016/01/07 02:26:09 Thanks! I've done this, although made it not tempo
jam 2016/01/08 22:37:40 great, i had some more statements in this comment
+ &received_handles);
+ CHECK_EQ(1, result);
+ CHECK_EQ(1u, received_handles.size());
+ parent_async_channel_handle.reset(received_handles.front());
#else
- // On Windows we have two pipes to the parent. The first is for the token
- // exchange for creating and passing handles, since the child needs the
- // parent's help if it is sandboxed. The second is the same as POSIX, which is
- // used for multiplexing related messages. So on Windows, we send the second
- // pipe as the first string over the first one.
- parent_sync_channel_ = handle.Pass();
-
HANDLE parent_handle = INVALID_HANDLE_VALUE;
DWORD bytes_read = 0;
BOOL rv = ReadFile(parent_sync_channel_.get().handle, &parent_handle,
sizeof(parent_handle), &bytes_read, NULL);
CHECK(rv);
parent_async_channel_handle.reset(PlatformHandle(parent_handle));
- sync_channel_lock_.Unlock();
#endif
+ sync_channel_lock_.Unlock();
internal::g_io_thread_task_runner->PostTask(
FROM_HERE,
@@ -99,6 +111,16 @@ void ChildBroker::TokenToHandle(const uint64_t* tokens,
sync_channel_lock_.Unlock();
}
}
+#else
+scoped_refptr<PlatformSharedBuffer> ChildBroker::CreateSharedBuffer(
+ size_t num_bytes) {
+ sync_channel_lock_.Lock();
+ scoped_refptr<PlatformSharedBuffer> shared_buffer =
+ CreateSharedBufferNoLock(num_bytes);
jam 2016/01/06 02:58:16 no need to have two methods for this. you can inli
Eliot Courtney 2016/01/07 02:26:09 Done.
+ sync_channel_lock_.Unlock();
+
+ return shared_buffer;
+}
#endif
void ChildBroker::ConnectMessagePipe(uint64_t pipe_id,
@@ -172,10 +194,8 @@ ChildBroker::ChildBroker()
in_process_pipes_channel2_(nullptr) {
DCHECK(!internal::g_broker);
internal::g_broker = this;
-#if defined(OS_WIN)
// Block any threads from calling this until we have a pipe to the parent.
sync_channel_lock_.Lock();
-#endif
}
ChildBroker::~ChildBroker() {
@@ -285,12 +305,28 @@ void ChildBroker::AttachMessagePipe(MessagePipeDispatcher* message_pipe,
#if defined(OS_WIN)
+void ChildBroker::CreatePlatformChannelPairNoLock(
+ ScopedPlatformHandle* server,
+ ScopedPlatformHandle* client) {
+ BrokerMessage message;
+ message.size = kBrokerMessageHeaderSize;
+ message.id = CREATE_PLATFORM_CHANNEL_PAIR;
+
+ uint32_t response_size = 2 * sizeof(HANDLE);
+ HANDLE handles[2];
+ if (WriteAndReadResponse(&message, handles, response_size)) {
+ server->reset(PlatformHandle(handles[0]));
+ client->reset(PlatformHandle(handles[1]));
+ }
+}
+
bool ChildBroker::WriteAndReadResponse(BrokerMessage* message,
void* response,
uint32_t response_size) {
CHECK(parent_sync_channel_.is_valid());
bool result = true;
+
jam 2016/01/06 02:58:16 nit: no need to change
Eliot Courtney 2016/01/07 02:26:09 Done.
DWORD bytes_written = 0;
// This will always write in one chunk per
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150.aspx.
@@ -316,21 +352,65 @@ bool ChildBroker::WriteAndReadResponse(BrokerMessage* message,
return result;
}
-
-void ChildBroker::CreatePlatformChannelPairNoLock(
- ScopedPlatformHandle* server, ScopedPlatformHandle* client) {
+#else
+scoped_refptr<PlatformSharedBuffer> ChildBroker::CreateSharedBufferNoLock(
+ size_t num_bytes) {
BrokerMessage message;
- message.size = kBrokerMessageHeaderSize;
- message.id = CREATE_PLATFORM_CHANNEL_PAIR;
+ message.size = kBrokerMessageHeaderSize + sizeof(uint32_t);
+ message.id = CREATE_SHARED_BUFFER;
+ message.num_bytes = num_bytes;
+
+ std::deque<PlatformHandle> handles;
+ if (WriteAndReadHandles(&message, &handles)) {
+ DCHECK_EQ(1u, handles.size());
+ if (handles.empty()) {
+ LOG(ERROR)
+ << "ChildBroker did not receive handle when creating shared buffer";
+ return nullptr;
+ }
- uint32_t response_size = 2 * sizeof(HANDLE);
- HANDLE handles[2];
- if (WriteAndReadResponse(&message, handles, response_size)) {
- server->reset(PlatformHandle(handles[0]));
- client->reset(PlatformHandle(handles[1]));
+ PlatformHandle handle = handles.front();
+ if (handle.is_valid())
+ return internal::g_platform_support->CreateSharedBufferFromHandle(
+ num_bytes, ScopedPlatformHandle(handles.front()));
+ else
+ return nullptr;
}
+
+ return nullptr;
}
+bool ChildBroker::WriteAndReadHandles(BrokerMessage* message,
+ std::deque<PlatformHandle>* handles) {
+ CHECK(parent_sync_channel_.is_valid());
+
+ uint32_t remaining_bytes = message->size;
+ while (remaining_bytes > 0) {
+ ssize_t bytes_written = PlatformChannelWrite(
Eliot Courtney 2016/01/05 04:45:47 This loop is on top of a non-blocking function (Pl
jam 2016/01/06 02:58:16 i don't see how it would ever block in practice, b
Eliot Courtney 2016/01/07 02:26:09 I removed the O_NONBLOCK using fcntl like you sugg
+ parent_sync_channel_.get(),
+ reinterpret_cast<uint8_t*>(message) + (message->size - remaining_bytes),
+ remaining_bytes);
+
+ if (bytes_written == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
+ return false;
+
+ if (bytes_written != -1)
+ remaining_bytes -= bytes_written;
+ }
+
+ while (1) {
jam 2016/01/06 02:58:16 same as first comment in this file, why not make r
Eliot Courtney 2016/01/07 02:26:09 Done.
+ char buf[1];
+ ssize_t bytes_read =
+ PlatformChannelRecvmsg(parent_sync_channel_.get(), buf, 1, handles);
Eliot Courtney 2016/01/05 04:45:47 Same comment as above.
Eliot Courtney 2016/01/07 02:26:08 Done.
+ if (bytes_read == 0 ||
+ (bytes_read == -1 && errno != EAGAIN && errno != EWOULDBLOCK))
+ return false;
+
+ if (handles->size() >= 1)
+ break;
+ }
+ return true;
+}
#endif
} // namespace edk

Powered by Google App Engine
This is Rietveld 408576698