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

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

Issue 1524333002: Fix race condition with multiplexed message pipes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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.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.h" 5 #include "mojo/edk/system/child_broker.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "mojo/edk/embedder/embedder_internal.h" 9 #include "mojo/edk/embedder/embedder_internal.h"
10 #include "mojo/edk/embedder/platform_channel_pair.h" 10 #include "mojo/edk/embedder/platform_channel_pair.h"
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 client_handle = channel_pair.PassClientHandle(); 131 client_handle = channel_pair.PassClientHandle();
132 #endif 132 #endif
133 in_process_pipes_channel1_ = new RoutedRawChannel( 133 in_process_pipes_channel1_ = new RoutedRawChannel(
134 server_handle.Pass(), 134 server_handle.Pass(),
135 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this))); 135 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
136 in_process_pipes_channel2_ = new RoutedRawChannel( 136 in_process_pipes_channel2_ = new RoutedRawChannel(
137 client_handle.Pass(), 137 client_handle.Pass(),
138 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this))); 138 base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
139 } 139 }
140 140
141 connected_pipes_[pending_connects_[pipe_id]] = in_process_pipes_channel1_; 141 AttachMessagePipe(pending_connects_[pipe_id], pipe_id,
142 connected_pipes_[message_pipe] = in_process_pipes_channel2_; 142 in_process_pipes_channel1_);
143 in_process_pipes_channel1_->AddRoute(pipe_id, pending_connects_[pipe_id]); 143 AttachMessagePipe(message_pipe, pipe_id, in_process_pipes_channel2_);
144 in_process_pipes_channel2_->AddRoute(pipe_id, message_pipe);
145 pending_connects_[pipe_id]->GotNonTransferableChannel(
146 in_process_pipes_channel1_->channel());
147 message_pipe->GotNonTransferableChannel(
148 in_process_pipes_channel2_->channel());
149
150 pending_connects_.erase(pipe_id); 144 pending_connects_.erase(pipe_id);
151 return; 145 return;
152 } 146 }
153 147
154 data.type = CONNECT_MESSAGE_PIPE; 148 data.type = CONNECT_MESSAGE_PIPE;
155 scoped_ptr<MessageInTransit> message(new MessageInTransit( 149 scoped_ptr<MessageInTransit> message(new MessageInTransit(
156 MessageInTransit::Type::MESSAGE, sizeof(data), &data)); 150 MessageInTransit::Type::MESSAGE, sizeof(data), &data));
157 pending_connects_[pipe_id] = message_pipe; 151 pending_connects_[pipe_id] = message_pipe;
158 WriteAsyncMessage(message.Pass()); 152 WriteAsyncMessage(message.Pass());
159 } 153 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 static_cast<const PeerPipeConnectedMessage*>(message_view.bytes()); 199 static_cast<const PeerPipeConnectedMessage*>(message_view.bytes());
206 200
207 uint64_t pipe_id = message->pipe_id; 201 uint64_t pipe_id = message->pipe_id;
208 uint64_t peer_pid = message->process_id; 202 uint64_t peer_pid = message->process_id;
209 203
210 CHECK(pending_connects_.find(pipe_id) != pending_connects_.end()); 204 CHECK(pending_connects_.find(pipe_id) != pending_connects_.end());
211 MessagePipeDispatcher* pipe = pending_connects_[pipe_id]; 205 MessagePipeDispatcher* pipe = pending_connects_[pipe_id];
212 pending_connects_.erase(pipe_id); 206 pending_connects_.erase(pipe_id);
213 if (peer_pid == 0) { 207 if (peer_pid == 0) {
214 // The other side is in the parent process. 208 // The other side is in the parent process.
215 connected_pipes_[pipe] = parent_async_channel_; 209 AttachMessagePipe(pipe, pipe_id, parent_async_channel_);
216 parent_async_channel_->AddRoute(pipe_id, pipe);
217 pipe->GotNonTransferableChannel(parent_async_channel_->channel());
218 } else if (channels_.find(peer_pid) == channels_.end()) { 210 } else if (channels_.find(peer_pid) == channels_.end()) {
219 // We saw the peer process die before we got the reply from the parent. 211 // We saw the peer process die before we got the reply from the parent.
220 pipe->OnError(ERROR_READ_SHUTDOWN); 212 pipe->OnError(ERROR_READ_SHUTDOWN);
221 } else { 213 } else {
222 CHECK(connected_pipes_.find(pipe) == connected_pipes_.end()); 214 CHECK(connected_pipes_.find(pipe) == connected_pipes_.end());
223 connected_pipes_[pipe] = channels_[peer_pid]; 215 AttachMessagePipe(pipe, pipe_id, channels_[peer_pid]);
224 channels_[peer_pid]->AddRoute(pipe_id, pipe);
225 pipe->GotNonTransferableChannel(channels_[peer_pid]->channel());
226 } 216 }
227 } else { 217 } else {
228 NOTREACHED(); 218 NOTREACHED();
229 } 219 }
230 } 220 }
231 221
232 void ChildBroker::OnError(Error error) { 222 void ChildBroker::OnError(Error error) {
233 // The parent process shut down. 223 // The parent process shut down.
234 } 224 }
235 225
(...skipping 30 matching lines...) Expand all
266 async_channel_queue_.GetMessage()); 256 async_channel_queue_.GetMessage());
267 } 257 }
268 258
269 while (!pending_inprocess_connects_.empty()) { 259 while (!pending_inprocess_connects_.empty()) {
270 ConnectMessagePipe(pending_inprocess_connects_.begin()->first, 260 ConnectMessagePipe(pending_inprocess_connects_.begin()->first,
271 pending_inprocess_connects_.begin()->second); 261 pending_inprocess_connects_.begin()->second);
272 pending_inprocess_connects_.erase(pending_inprocess_connects_.begin()); 262 pending_inprocess_connects_.erase(pending_inprocess_connects_.begin());
273 } 263 }
274 } 264 }
275 265
266 void ChildBroker::AttachMessagePipe(MessagePipeDispatcher* message_pipe,
267 uint64_t pipe_id,
268 RoutedRawChannel* raw_channel) {
269 connected_pipes_[message_pipe] = raw_channel;
270 // Note: we must call GotNonTransferableChannel before AddRoute because there
271 // could be race conditions if the pipe got queued messages in |AddRoute| but
272 // then when it's read it returns no messages because it doesn't have the
273 // channel yet.
274 message_pipe->GotNonTransferableChannel(raw_channel->channel());
275 raw_channel->AddRoute(pipe_id, message_pipe);
276 }
277
276 #if defined(OS_WIN) 278 #if defined(OS_WIN)
277 279
278 bool ChildBroker::WriteAndReadResponse(BrokerMessage* message, 280 bool ChildBroker::WriteAndReadResponse(BrokerMessage* message,
279 void* response, 281 void* response,
280 uint32_t response_size) { 282 uint32_t response_size) {
281 CHECK(parent_sync_channel_.is_valid()); 283 CHECK(parent_sync_channel_.is_valid());
282 284
283 bool result = true; 285 bool result = true;
284 DWORD bytes_written = 0; 286 DWORD bytes_written = 0;
285 // This will always write in one chunk per 287 // This will always write in one chunk per
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 if (WriteAndReadResponse(&message, handles, response_size)) { 320 if (WriteAndReadResponse(&message, handles, response_size)) {
319 server->reset(PlatformHandle(handles[0])); 321 server->reset(PlatformHandle(handles[0]));
320 client->reset(PlatformHandle(handles[1])); 322 client->reset(PlatformHandle(handles[1]));
321 } 323 }
322 } 324 }
323 325
324 #endif 326 #endif
325 327
326 } // namespace edk 328 } // namespace edk
327 } // namespace mojo 329 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/child_broker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698