| Index: mojo/system/channel.cc
|
| diff --git a/mojo/system/channel.cc b/mojo/system/channel.cc
|
| index 0c4033fcac2ba70071e2aeee32bcb32fe2695ab0..18c2df18b4716356d3214a7c472351cd21ec8891 100644
|
| --- a/mojo/system/channel.cc
|
| +++ b/mojo/system/channel.cc
|
| @@ -417,8 +417,8 @@ void Channel::OnReadMessageForChannel(
|
| DVLOG(2) << "Handling channel message to remove message pipe (local ID "
|
| << message_view.destination_id() << ", remote ID "
|
| << message_view.source_id() << ")";
|
| - if (!RemoveMessagePipeEndpoint(message_view.destination_id(),
|
| - message_view.source_id())) {
|
| + if (!OnRemoveMessagePipeEndpoint(message_view.destination_id(),
|
| + message_view.source_id())) {
|
| HandleRemoteError(
|
| "Received invalid channel message to remove message pipe");
|
| }
|
| @@ -427,8 +427,7 @@ void Channel::OnReadMessageForChannel(
|
| DVLOG(2) << "Handling channel message to ack remove message pipe (local "
|
| "ID " << message_view.destination_id() << ", remote ID "
|
| << message_view.source_id() << ")";
|
| - if (!RemoveMessagePipeEndpoint(message_view.destination_id(),
|
| - message_view.source_id())) {
|
| + if (!OnRemoveMessagePipeEndpointAck(message_view.destination_id())) {
|
| HandleRemoteError(
|
| "Received invalid channel message to ack remove message pipe");
|
| }
|
| @@ -440,14 +439,11 @@ void Channel::OnReadMessageForChannel(
|
| }
|
| }
|
|
|
| -bool Channel::RemoveMessagePipeEndpoint(
|
| +bool Channel::OnRemoveMessagePipeEndpoint(
|
| MessageInTransit::EndpointId local_id,
|
| MessageInTransit::EndpointId remote_id) {
|
| DCHECK(creation_thread_checker_.CalledOnValidThread());
|
|
|
| - // If this is non-null after the locked block, the endpoint should be detached
|
| - // (and no remove ack message sent).
|
| - scoped_refptr<ChannelEndpoint> endpoint_to_detach;
|
| scoped_refptr<MessagePipe> message_pipe;
|
| unsigned port = ~0u;
|
| {
|
| @@ -455,31 +451,31 @@ bool Channel::RemoveMessagePipeEndpoint(
|
|
|
| IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
|
| if (it == local_id_to_endpoint_map_.end()) {
|
| - DVLOG(2) << "Remove message pipe error: not found";
|
| + DVLOG(2) << "Remove message pipe endpoint error: not found";
|
| return false;
|
| }
|
|
|
| switch (it->second->state_) {
|
| case ChannelEndpoint::STATE_NORMAL:
|
| - it->second->state_ = ChannelEndpoint::STATE_WAIT_LOCAL_DETACH;
|
| - message_pipe = it->second->message_pipe_;
|
| - port = it->second->port_;
|
| - it->second->message_pipe_ = nullptr;
|
| - // We have to send a remove ack message (outside the lock).
|
| + // This is the normal case; we'll proceed on to "wait local detach".
|
| break;
|
| +
|
| case ChannelEndpoint::STATE_WAIT_LOCAL_DETACH:
|
| - DVLOG(2) << "Remove message pipe error: wrong state";
|
| + // We can only be in this state because we got a "remove" already, so
|
| + // getting another such message is invalid.
|
| + DVLOG(2) << "Remove message pipe endpoint error: wrong state";
|
| return false;
|
| +
|
| case ChannelEndpoint::STATE_WAIT_REMOTE_REMOVE_ACK:
|
| - endpoint_to_detach = it->second;
|
| - local_id_to_endpoint_map_.erase(it);
|
| - // We have to detach (outside the lock).
|
| - break;
|
| + // Remove messages "crossed"; we have to wait for the ack.
|
| + return true;
|
| }
|
| - }
|
| - if (endpoint_to_detach.get()) {
|
| - endpoint_to_detach->DetachFromChannel();
|
| - return true;
|
| +
|
| + it->second->state_ = ChannelEndpoint::STATE_WAIT_LOCAL_DETACH;
|
| + message_pipe = it->second->message_pipe_;
|
| + port = it->second->port_;
|
| + it->second->message_pipe_ = nullptr;
|
| + // Send the remove ack message outside the lock.
|
| }
|
|
|
| if (!SendControlMessage(
|
| @@ -494,7 +490,34 @@ bool Channel::RemoveMessagePipeEndpoint(
|
| }
|
|
|
| message_pipe->Close(port);
|
| + return true;
|
| +}
|
| +
|
| +bool Channel::OnRemoveMessagePipeEndpointAck(
|
| + MessageInTransit::EndpointId local_id) {
|
| + DCHECK(creation_thread_checker_.CalledOnValidThread());
|
| +
|
| + scoped_refptr<ChannelEndpoint> endpoint_to_detach;
|
| + {
|
| + base::AutoLock locker(lock_);
|
| +
|
| + IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
|
| + if (it == local_id_to_endpoint_map_.end()) {
|
| + DVLOG(2) << "Remove message pipe endpoint ack error: not found";
|
| + return false;
|
| + }
|
| +
|
| + if (it->second->state_ != ChannelEndpoint::STATE_WAIT_REMOTE_REMOVE_ACK) {
|
| + DVLOG(2) << "Remove message pipe endpoint ack error: wrong state";
|
| + return false;
|
| + }
|
| +
|
| + endpoint_to_detach = it->second;
|
| + local_id_to_endpoint_map_.erase(it);
|
| + // Detach the endpoint outside the lock.
|
| + }
|
|
|
| + endpoint_to_detach->DetachFromChannel();
|
| return true;
|
| }
|
|
|
|
|