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

Side by Side Diff: mojo/system/channel.cc

Issue 240133005: Mojo: Make some attempts towards fixing remote message pipe closure. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix some locking issues Created 6 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « mojo/system/channel.h ('k') | mojo/system/local_message_pipe_endpoint.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/system/channel.h" 5 #include "mojo/system/channel.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
12 #include "mojo/system/message_pipe_endpoint.h" 12 #include "mojo/system/message_pipe_endpoint.h"
13 13
14 namespace mojo { 14 namespace mojo {
15 namespace system { 15 namespace system {
16 16
17 COMPILE_ASSERT(Channel::kBootstrapEndpointId != 17 COMPILE_ASSERT(Channel::kBootstrapEndpointId !=
18 MessageInTransit::kInvalidEndpointId, 18 MessageInTransit::kInvalidEndpointId,
19 kBootstrapEndpointId_is_invalid); 19 kBootstrapEndpointId_is_invalid);
20 20
21 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId 21 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId
22 Channel::kBootstrapEndpointId; 22 Channel::kBootstrapEndpointId;
23 23
24 Channel::EndpointInfo::EndpointInfo() { 24 Channel::EndpointInfo::EndpointInfo()
25 : state(STATE_NORMAL),
26 port() {
25 } 27 }
26 28
27 Channel::EndpointInfo::EndpointInfo(scoped_refptr<MessagePipe> message_pipe, 29 Channel::EndpointInfo::EndpointInfo(scoped_refptr<MessagePipe> message_pipe,
28 unsigned port) 30 unsigned port)
29 : message_pipe(message_pipe), 31 : state(STATE_NORMAL),
32 message_pipe(message_pipe),
30 port(port) { 33 port(port) {
31 } 34 }
32 35
33 Channel::EndpointInfo::~EndpointInfo() { 36 Channel::EndpointInfo::~EndpointInfo() {
34 } 37 }
35 38
36 Channel::Channel() 39 Channel::Channel()
37 : next_local_id_(kBootstrapEndpointId) { 40 : next_local_id_(kBootstrapEndpointId) {
38 } 41 }
39 42
(...skipping 15 matching lines...) Expand all
55 } 58 }
56 59
57 void Channel::Shutdown() { 60 void Channel::Shutdown() {
58 DCHECK(creation_thread_checker_.CalledOnValidThread()); 61 DCHECK(creation_thread_checker_.CalledOnValidThread());
59 62
60 base::AutoLock locker(lock_); 63 base::AutoLock locker(lock_);
61 DCHECK(raw_channel_.get()); 64 DCHECK(raw_channel_.get());
62 raw_channel_->Shutdown(); 65 raw_channel_->Shutdown();
63 raw_channel_.reset(); 66 raw_channel_.reset();
64 67
65 // This should not occur, but it probably mostly results in leaking; 68 // This shouldn't usually occur, but it should be okay if all the endpoints
66 // (Explicitly clearing the |local_id_to_endpoint_info_map_| would likely put 69 // are zombies (i.e., waiting to be removed, and not actually having any
67 // things in an inconsistent state, which is worse. Note that if the map is 70 // references to |MessagePipe|s).
68 // nonempty, we probably won't be destroyed, since the endpoints have a 71 // TODO(vtl): To make this actually okay, we need to make sure the other side
69 // reference to us.) 72 // channels being killed off properly.
70 LOG_IF(ERROR, !local_id_to_endpoint_info_map_.empty()) 73 LOG_IF(WARNING, !local_id_to_endpoint_info_map_.empty())
71 << "Channel shutting down with endpoints still attached"; 74 << "Channel shutting down with endpoints still attached "
72 // TODO(vtl): This currently blows up, but the fix will be nontrivial. 75 "(hopefully all zombies)";
73 // crbug.com/360081 76
74 //DCHECK(local_id_to_endpoint_info_map_.empty()); 77 #ifndef NDEBUG
78 // Check that everything left is a zombie. (Note: We don't explicitly clear
79 // |local_id_to_endpoint_info_map_|, since that would likely put us in an
80 // inconsistent state if we have non-zombies.)
81 for (IdToEndpointInfoMap::const_iterator it =
82 local_id_to_endpoint_info_map_.begin();
83 it != local_id_to_endpoint_info_map_.end();
84 ++it) {
85 DCHECK_NE(it->second.state, EndpointInfo::STATE_NORMAL);
86 DCHECK(!it->second.message_pipe.get());
87 }
88 #endif
75 } 89 }
76 90
77 MessageInTransit::EndpointId Channel::AttachMessagePipeEndpoint( 91 MessageInTransit::EndpointId Channel::AttachMessagePipeEndpoint(
78 scoped_refptr<MessagePipe> message_pipe, unsigned port) { 92 scoped_refptr<MessagePipe> message_pipe,
93 unsigned port) {
94 DCHECK(message_pipe);
79 DCHECK(port == 0 || port == 1); 95 DCHECK(port == 0 || port == 1);
80 // Note: This assertion must *not* be done under |lock_|.
81 DCHECK_EQ(message_pipe->GetType(port), MessagePipeEndpoint::kTypeProxy);
82 96
83 MessageInTransit::EndpointId local_id; 97 MessageInTransit::EndpointId local_id;
84 { 98 {
85 base::AutoLock locker(lock_); 99 base::AutoLock locker(lock_);
86 100
87 while (next_local_id_ == MessageInTransit::kInvalidEndpointId || 101 while (next_local_id_ == MessageInTransit::kInvalidEndpointId ||
88 local_id_to_endpoint_info_map_.find(next_local_id_) != 102 local_id_to_endpoint_info_map_.find(next_local_id_) !=
89 local_id_to_endpoint_info_map_.end()) 103 local_id_to_endpoint_info_map_.end())
90 next_local_id_++; 104 next_local_id_++;
91 105
92 local_id = next_local_id_; 106 local_id = next_local_id_;
93 next_local_id_++; 107 next_local_id_++;
94 108
95 // TODO(vtl): Use emplace when we move to C++11 unordered_maps. (It'll avoid 109 // TODO(vtl): Use emplace when we move to C++11 unordered_maps. (It'll avoid
96 // some expensive reference count increment/decrements.) Once this is done, 110 // some expensive reference count increment/decrements.) Once this is done,
97 // we should be able to delete |EndpointInfo|'s default constructor. 111 // we should be able to delete |EndpointInfo|'s default constructor.
98 local_id_to_endpoint_info_map_[local_id] = EndpointInfo(message_pipe, port); 112 local_id_to_endpoint_info_map_[local_id] = EndpointInfo(message_pipe, port);
99 } 113 }
100 114
101 message_pipe->Attach(port, scoped_refptr<Channel>(this), local_id); 115 // This might fail if that port got an |OnPeerClose()| before attaching.
102 return local_id; 116 if (message_pipe->Attach(port, scoped_refptr<Channel>(this), local_id))
117 return local_id;
118
119 // Note: If it failed, quite possibly the endpoint info was removed from that
120 // map (there's a race between us adding it to the map above and calling
121 // |Attach()|). And even if an entry exists for |local_id|, we need to check
122 // that it's the one we added (and not some other one that was added since).
123 {
124 base::AutoLock locker(lock_);
125 IdToEndpointInfoMap::iterator it =
126 local_id_to_endpoint_info_map_.find(local_id);
127 if (it != local_id_to_endpoint_info_map_.end() &&
128 it->second.message_pipe.get() == message_pipe.get() &&
129 it->second.port == port) {
130 DCHECK_EQ(it->second.state, EndpointInfo::STATE_NORMAL);
131 // TODO(vtl): FIXME -- This is wrong. We need to specify (to
132 // |AttachMessagePipeEndpoint()| who's going to be responsible for calling
133 // |RunMessagePipeEndpoint()| ("us", or the remote by sending us a
134 // |kSubtypeChannelRunMessagePipeEndpoint|). If the remote is going to
135 // run, then we'll get messages to an "invalid" local ID (for running, for
136 // removal).
137 local_id_to_endpoint_info_map_.erase(it);
138 }
139 }
140 return MessageInTransit::kInvalidEndpointId;
103 } 141 }
104 142
105 bool Channel::RunMessagePipeEndpoint(MessageInTransit::EndpointId local_id, 143 bool Channel::RunMessagePipeEndpoint(MessageInTransit::EndpointId local_id,
106 MessageInTransit::EndpointId remote_id) { 144 MessageInTransit::EndpointId remote_id) {
107 EndpointInfo endpoint_info; 145 EndpointInfo endpoint_info;
108 { 146 {
109 base::AutoLock locker(lock_); 147 base::AutoLock locker(lock_);
110 148
111 IdToEndpointInfoMap::const_iterator it = 149 IdToEndpointInfoMap::const_iterator it =
112 local_id_to_endpoint_info_map_.find(local_id); 150 local_id_to_endpoint_info_map_.find(local_id);
113 if (it == local_id_to_endpoint_info_map_.end()) 151 if (it == local_id_to_endpoint_info_map_.end())
114 return false; 152 return false;
115 endpoint_info = it->second; 153 endpoint_info = it->second;
116 } 154 }
117 155
156 // Assume that this was in response to |kSubtypeChannelRunMessagePipeEndpoint|
157 // and ignore it.
158 if (endpoint_info.state != EndpointInfo::STATE_NORMAL) {
159 DVLOG(2) << "Ignoring run message pipe endpoint for zombie endpoint "
160 "(local ID " << local_id << ", remote ID " << remote_id << ")";
161 return true;
162 }
163
118 // TODO(vtl): FIXME -- We need to handle the case that message pipe is already 164 // TODO(vtl): FIXME -- We need to handle the case that message pipe is already
119 // running when we're here due to |kSubtypeChannelRunMessagePipeEndpoint|). 165 // running when we're here due to |kSubtypeChannelRunMessagePipeEndpoint|).
120 endpoint_info.message_pipe->Run(endpoint_info.port, remote_id); 166 endpoint_info.message_pipe->Run(endpoint_info.port, remote_id);
121 return true; 167 return true;
122 } 168 }
123 169
124 void Channel::RunRemoteMessagePipeEndpoint( 170 void Channel::RunRemoteMessagePipeEndpoint(
125 MessageInTransit::EndpointId local_id, 171 MessageInTransit::EndpointId local_id,
126 MessageInTransit::EndpointId remote_id) { 172 MessageInTransit::EndpointId remote_id) {
127 base::AutoLock locker(lock_); 173 #if DCHECK_IS_ON
174 {
175 base::AutoLock locker(lock_);
176 DCHECK(local_id_to_endpoint_info_map_.find(local_id) !=
177 local_id_to_endpoint_info_map_.end());
178 }
179 #endif
128 180
129 DCHECK(local_id_to_endpoint_info_map_.find(local_id) != 181 if (!SendControlMessage(
130 local_id_to_endpoint_info_map_.end()); 182 MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint,
131 183 local_id, remote_id)) {
132 scoped_ptr<MessageInTransit> message(new MessageInTransit( 184 HandleLocalError(base::StringPrintf(
133 MessageInTransit::kTypeChannel, 185 "Failed to send message to run remote message pipe endpoint (local ID "
134 MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint, 186 "%u, remote ID %u)",
135 0, 0, NULL)); 187 static_cast<unsigned>(local_id), static_cast<unsigned>(remote_id)));
136 message->set_source_id(local_id);
137 message->set_destination_id(remote_id);
138 if (!raw_channel_->WriteMessage(message.Pass())) {
139 // TODO(vtl): FIXME -- I guess we should report the error back somehow so
140 // that the dispatcher can be closed?
141 CHECK(false) << "Not yet handled";
142 } 188 }
143 } 189 }
144 190
145 bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) { 191 bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) {
146 base::AutoLock locker(lock_); 192 base::AutoLock locker(lock_);
147 if (!raw_channel_.get()) { 193 if (!raw_channel_.get()) {
148 // TODO(vtl): I think this is probably not an error condition, but I should 194 // TODO(vtl): I think this is probably not an error condition, but I should
149 // think about it (and the shutdown sequence) more carefully. 195 // think about it (and the shutdown sequence) more carefully.
150 LOG(WARNING) << "WriteMessage() after shutdown"; 196 LOG(WARNING) << "WriteMessage() after shutdown";
151 return false; 197 return false;
152 } 198 }
153 199
154 return raw_channel_->WriteMessage(message.Pass()); 200 return raw_channel_->WriteMessage(message.Pass());
155 } 201 }
156 202
157 bool Channel::IsWriteBufferEmpty() { 203 bool Channel::IsWriteBufferEmpty() {
158 base::AutoLock locker(lock_); 204 base::AutoLock locker(lock_);
159 DCHECK(raw_channel_.get()); 205 DCHECK(raw_channel_.get());
160 return raw_channel_->IsWriteBufferEmpty(); 206 return raw_channel_->IsWriteBufferEmpty();
161 } 207 }
162 208
163 void Channel::DetachMessagePipeEndpoint(MessageInTransit::EndpointId local_id) { 209 void Channel::DetachMessagePipeEndpoint(
210 MessageInTransit::EndpointId local_id,
211 MessageInTransit::EndpointId remote_id) {
164 DCHECK_NE(local_id, MessageInTransit::kInvalidEndpointId); 212 DCHECK_NE(local_id, MessageInTransit::kInvalidEndpointId);
165 213
166 base::AutoLock locker_(lock_); 214 bool should_send_remove_message = false;
167 local_id_to_endpoint_info_map_.erase(local_id); 215 {
216 base::AutoLock locker_(lock_);
217 IdToEndpointInfoMap::iterator it =
218 local_id_to_endpoint_info_map_.find(local_id);
219 DCHECK(it != local_id_to_endpoint_info_map_.end());
220
221 switch (it->second.state) {
222 case EndpointInfo::STATE_NORMAL:
223 it->second.state = EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK;
224 it->second.message_pipe = NULL;
225 should_send_remove_message =
226 (remote_id != MessageInTransit::kInvalidEndpointId);
227 break;
228 case EndpointInfo::STATE_WAIT_LOCAL_DETACH:
229 local_id_to_endpoint_info_map_.erase(it);
230 break;
231 case EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK:
232 NOTREACHED();
233 break;
234 case EndpointInfo::STATE_WAIT_LOCAL_DETACH_AND_REMOTE_REMOVE_ACK:
235 it->second.state = EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK;
236 break;
237 }
238 }
239 if (!should_send_remove_message)
240 return;
241
242 if (!SendControlMessage(
243 MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint,
244 local_id, remote_id)) {
245 HandleLocalError(base::StringPrintf(
246 "Failed to send message to remove remote message pipe endpoint (local "
247 "ID %u, remote ID %u)",
248 static_cast<unsigned>(local_id), static_cast<unsigned>(remote_id)));
249 }
168 } 250 }
169 251
170 Channel::~Channel() { 252 Channel::~Channel() {
171 // The channel should have been shut down first. 253 // The channel should have been shut down first.
172 DCHECK(!raw_channel_.get()); 254 DCHECK(!raw_channel_.get());
173
174 DLOG_IF(WARNING, !local_id_to_endpoint_info_map_.empty())
175 << "Destroying Channel with " << local_id_to_endpoint_info_map_.size()
176 << " endpoints still present";
177 } 255 }
178 256
179 void Channel::OnReadMessage(const MessageInTransit::View& message_view) { 257 void Channel::OnReadMessage(const MessageInTransit::View& message_view) {
180 // Note: |ValidateReadMessage()| will call |HandleRemoteError()| if necessary. 258 // Note: |ValidateReadMessage()| will call |HandleRemoteError()| if necessary.
181 if (!ValidateReadMessage(message_view)) 259 if (!ValidateReadMessage(message_view))
182 return; 260 return;
183 261
184 switch (message_view.type()) { 262 switch (message_view.type()) {
185 case MessageInTransit::kTypeMessagePipeEndpoint: 263 case MessageInTransit::kTypeMessagePipeEndpoint:
186 case MessageInTransit::kTypeMessagePipe: 264 case MessageInTransit::kTypeMessagePipe:
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 // This is strongly indicative of some problem. However, it's not a fatal 320 // This is strongly indicative of some problem. However, it's not a fatal
243 // error, since it may indicate a bug (or hostile) remote process. Don't 321 // error, since it may indicate a bug (or hostile) remote process. Don't
244 // die even for Debug builds, since handling this properly needs to be 322 // die even for Debug builds, since handling this properly needs to be
245 // tested (TODO(vtl)). 323 // tested (TODO(vtl)).
246 DLOG(ERROR) << "This should not happen under normal operation."; 324 DLOG(ERROR) << "This should not happen under normal operation.";
247 return; 325 return;
248 } 326 }
249 endpoint_info = it->second; 327 endpoint_info = it->second;
250 } 328 }
251 329
330 // Ignore messages for zombie endpoints (not an error).
331 if (endpoint_info.state != EndpointInfo::STATE_NORMAL) {
332 DVLOG(2) << "Ignoring downstream message for zombie endpoint (local ID = "
333 << local_id << ", remote ID = " << message_view.source_id() << ")";
334 return;
335 }
336
252 // We need to duplicate the message, because |EnqueueMessage()| will take 337 // We need to duplicate the message, because |EnqueueMessage()| will take
253 // ownership of it. 338 // ownership of it.
254 scoped_ptr<MessageInTransit> message(new MessageInTransit(message_view)); 339 scoped_ptr<MessageInTransit> message(new MessageInTransit(message_view));
255 message->DeserializeDispatchers(this); 340 message->DeserializeDispatchers(this);
256 MojoResult result = endpoint_info.message_pipe->EnqueueMessage( 341 MojoResult result = endpoint_info.message_pipe->EnqueueMessage(
257 MessagePipe::GetPeerPort(endpoint_info.port), message.Pass(), NULL); 342 MessagePipe::GetPeerPort(endpoint_info.port), message.Pass(), NULL);
258 if (result != MOJO_RESULT_OK) { 343 if (result != MOJO_RESULT_OK) {
259 // TODO(vtl): This might be a "non-error", e.g., if the destination endpoint 344 // TODO(vtl): This might be a "non-error", e.g., if the destination endpoint
260 // has been closed (in an unavoidable race). This might also be a "remote" 345 // has been closed (in an unavoidable race). This might also be a "remote"
261 // error, e.g., if the remote side is sending invalid control messages (to 346 // error, e.g., if the remote side is sending invalid control messages (to
262 // the message pipe). 347 // the message pipe).
263 HandleLocalError(base::StringPrintf( 348 HandleLocalError(base::StringPrintf(
264 "Failed to enqueue message to local destination ID %u (result %d)", 349 "Failed to enqueue message to local ID %u (result %d)",
265 static_cast<unsigned>(local_id), static_cast<int>(result))); 350 static_cast<unsigned>(local_id), static_cast<int>(result)));
266 return; 351 return;
267 } 352 }
268 } 353 }
269 354
270 void Channel::OnReadMessageForChannel( 355 void Channel::OnReadMessageForChannel(
271 const MessageInTransit::View& message_view) { 356 const MessageInTransit::View& message_view) {
272 DCHECK_EQ(message_view.type(), MessageInTransit::kTypeChannel); 357 DCHECK_EQ(message_view.type(), MessageInTransit::kTypeChannel);
273 358
274 switch (message_view.subtype()) { 359 switch (message_view.subtype()) {
275 case MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint: 360 case MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint:
276 // TODO(vtl): FIXME -- Error handling (also validation of 361 DVLOG(2) << "Handling channel message to run message pipe (local ID "
277 // source/destination IDs). 362 << message_view.destination_id() << ", remote ID "
278 DVLOG(2) << "Handling channel message to run message pipe (local ID = "
279 << message_view.destination_id() << ", remote ID = "
280 << message_view.source_id() << ")"; 363 << message_view.source_id() << ")";
281 if (!RunMessagePipeEndpoint(message_view.destination_id(), 364 if (!RunMessagePipeEndpoint(message_view.destination_id(),
282 message_view.source_id())) 365 message_view.source_id())) {
283 HandleRemoteError("Received invalid channel run message pipe message"); 366 HandleRemoteError(
367 "Received invalid channel message to run message pipe");
368 }
369 break;
370 case MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint:
371 DVLOG(2) << "Handling channel message to remove message pipe (local ID "
372 << message_view.destination_id() << ", remote ID "
373 << message_view.source_id() << ")";
374 if (!RemoveMessagePipeEndpoint(message_view.destination_id(),
375 message_view.source_id())) {
376 HandleRemoteError(
377 "Received invalid channel message to remove message pipe");
378 }
379 break;
380 case MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck:
381 DVLOG(2) << "Handling channel message to ack remove message pipe (local "
382 "ID "
383 << message_view.destination_id() << ", remote ID "
384 << message_view.source_id() << ")";
385 if (!RemoveMessagePipeEndpoint(message_view.destination_id(),
386 message_view.source_id())) {
387 HandleRemoteError(
388 "Received invalid channel message to ack remove message pipe");
389 }
284 break; 390 break;
285 default: 391 default:
286 HandleRemoteError("Received invalid channel message"); 392 HandleRemoteError("Received invalid channel message");
287 NOTREACHED(); 393 NOTREACHED();
288 break; 394 break;
289 } 395 }
290 } 396 }
291 397
398 bool Channel::RemoveMessagePipeEndpoint(
399 MessageInTransit::EndpointId local_id,
400 MessageInTransit::EndpointId remote_id) {
401 EndpointInfo endpoint_info;
402 {
403 base::AutoLock locker(lock_);
404
405 IdToEndpointInfoMap::iterator it =
406 local_id_to_endpoint_info_map_.find(local_id);
407 if (it == local_id_to_endpoint_info_map_.end()) {
408 DVLOG(2) << "Remove message pipe error: not found";
409 return false;
410 }
411
412 // If it's waiting for the remove ack, just do it and return.
413 if (it->second.state == EndpointInfo::STATE_WAIT_REMOTE_REMOVE_ACK) {
414 local_id_to_endpoint_info_map_.erase(it);
415 return true;
416 }
417
418 if (it->second.state != EndpointInfo::STATE_NORMAL) {
419 DVLOG(2) << "Remove message pipe error: wrong state";
420 return false;
421 }
422
423 it->second.state = EndpointInfo::STATE_WAIT_LOCAL_DETACH;
424 endpoint_info = it->second;
425 it->second.message_pipe = NULL;
426 }
427
428 if (!SendControlMessage(
429 MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck,
430 local_id, remote_id)) {
431 HandleLocalError(base::StringPrintf(
432 "Failed to send message to remove remote message pipe endpoint ack "
433 "(local ID %u, remote ID %u)",
434 static_cast<unsigned>(local_id), static_cast<unsigned>(remote_id)));
435 }
436
437 endpoint_info.message_pipe->OnRemove(endpoint_info.port);
438
439 return true;
440 }
441
442 bool Channel::SendControlMessage(MessageInTransit::Subtype subtype,
443 MessageInTransit::EndpointId local_id,
444 MessageInTransit::EndpointId remote_id) {
445 DVLOG(2) << "Sending channel control message: subtype " << subtype
446 << ", local ID " << local_id << ", remote ID " << remote_id;
447 scoped_ptr<MessageInTransit> message(new MessageInTransit(
448 MessageInTransit::kTypeChannel, subtype, 0, 0, NULL));
449 message->set_source_id(local_id);
450 message->set_destination_id(remote_id);
451 return WriteMessage(message.Pass());
452 }
453
292 void Channel::HandleRemoteError(const base::StringPiece& error_message) { 454 void Channel::HandleRemoteError(const base::StringPiece& error_message) {
293 // TODO(vtl): Is this how we really want to handle this? Probably we want to 455 // TODO(vtl): Is this how we really want to handle this? Probably we want to
294 // terminate the connection, since it's spewing invalid stuff. 456 // terminate the connection, since it's spewing invalid stuff.
295 LOG(WARNING) << error_message; 457 LOG(WARNING) << error_message;
296 } 458 }
297 459
298 void Channel::HandleLocalError(const base::StringPiece& error_message) { 460 void Channel::HandleLocalError(const base::StringPiece& error_message) {
299 // TODO(vtl): Is this how we really want to handle this? 461 // TODO(vtl): Is this how we really want to handle this?
462 // Sometimes we'll want to propagate the error back to the message pipe
463 // (endpoint), and notify it that the remote is (effectively) closed.
464 // Sometimes we'll want to kill the channel (and notify all the endpoints that
465 // their remotes are dead.
300 LOG(WARNING) << error_message; 466 LOG(WARNING) << error_message;
301 } 467 }
302 468
303 } // namespace system 469 } // namespace system
304 } // namespace mojo 470 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/system/channel.h ('k') | mojo/system/local_message_pipe_endpoint.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698