diff options
Diffstat (limited to 'mojo')
-rw-r--r-- | mojo/edk/system/broker_messages.h | 24 | ||||
-rw-r--r-- | mojo/edk/system/broker_state.cc | 41 | ||||
-rw-r--r-- | mojo/edk/system/child_broker.cc | 11 | ||||
-rw-r--r-- | mojo/edk/system/child_broker_host.cc | 13 | ||||
-rw-r--r-- | mojo/edk/system/child_broker_host.h | 4 | ||||
-rw-r--r-- | mojo/edk/system/message_pipe_dispatcher.cc | 4 |
6 files changed, 80 insertions, 17 deletions
diff --git a/mojo/edk/system/broker_messages.h b/mojo/edk/system/broker_messages.h index 0ce0960..13fe980 100644 --- a/mojo/edk/system/broker_messages.h +++ b/mojo/edk/system/broker_messages.h @@ -53,12 +53,31 @@ const uint64_t kBrokerRouteId = 1; // They are sent over RawChannel. enum MultiplexMessages { // Messages from child to parent. + + // Tells the parent that the given pipe id has been bound to a + // MessagePipeDispatcher in the child process. The parent will then respond + // with either PEER_PIPE_CONNECTED or PEER_DIED when the other side is also + // bound. CONNECT_MESSAGE_PIPE = 0, + // Tells the parent to remove its bookkeeping for the given peer id since + // another MessagePipeDispatcher has connected to the pipe in the same + // process. CANCEL_CONNECT_MESSAGE_PIPE, + // Messages from parent to child. + + // Tells the child to open a channel to a given process. This will be followed + // by a PEER_PIPE_CONNECTED connecting a message pipe from the child process + // to the given process over the new channel. CONNECT_TO_PROCESS, + + // Connect a given message pipe to another process. PEER_PIPE_CONNECTED, + + // Informs the child that the other end of the message pipe is in a process + // that died. + PEER_DIED, }; struct ConnectMessagePipeMessage { @@ -79,6 +98,11 @@ struct PeerPipeConnectedMessage { base::ProcessId process_id; }; +struct PeerDiedMessage { + MultiplexMessages type; // PEER_DIED + uint64_t pipe_id; +}; + } // namespace edk } // namespace mojo diff --git a/mojo/edk/system/broker_state.cc b/mojo/edk/system/broker_state.cc index 90ea00d..a81f1a1 100644 --- a/mojo/edk/system/broker_state.cc +++ b/mojo/edk/system/broker_state.cc @@ -93,8 +93,13 @@ void BrokerState::ConnectMessagePipe(uint64_t pipe_id, if (pending_child_connects_.find(pipe_id) != pending_child_connects_.end()) { // A child process has already tried to connect. ChildBrokerHost* child_host = pending_child_connects_[pipe_id]; - AttachMessagePipe(message_pipe, pipe_id, child_host->channel()); - child_host->ConnectMessagePipe(pipe_id, 0); + if (child_host && child_host->channel()) { + AttachMessagePipe(message_pipe, pipe_id, child_host->channel()); + child_host->ConnectMessagePipe(pipe_id, 0); + } else { + message_pipe->OnError(RawChannel::Delegate::ERROR_READ_SHUTDOWN); + } + pending_child_connects_.erase(pipe_id); return; } @@ -124,14 +129,12 @@ void BrokerState::ChildBrokerHostDestructed( base::AutoLock auto_lock(lock_); for (auto it = pending_child_connects_.begin(); - it != pending_child_connects_.end();) { + it != pending_child_connects_.end(); ++it) { if (it->second == child_broker_host) { - // Since we can't do it = pending_child_connects_.erase(it); until - // hash_map uses unordered_map on posix. - auto cur = it++; - pending_child_connects_.erase(cur); - } else { - it++; + // Signify that the process has died. When another process tries to + // connect to the message pipe, we will tell it that the peer has died so + // that it can fire a peer closed notification. + it->second = nullptr; } } @@ -139,8 +142,8 @@ void BrokerState::ChildBrokerHostDestructed( for (auto it = connected_processes_.begin(); it != connected_processes_.end();) { if ((*it).first == pid || (*it).second == pid) { - // Since we can't do it = pending_child_connects_.erase(it); until - // hash_map uses unordered_map on posix. + // Since we can't do it = connected_processes_.erase(it); until hash_map + // uses unordered_map on posix. auto cur = it++; connected_processes_.erase(cur); } else { @@ -159,12 +162,16 @@ void BrokerState::HandleConnectMessagePipe(ChildBrokerHost* pipe_process, if (pending_child_connects_.find(pipe_id) != pending_child_connects_.end()) { // Another child process is waiting to connect to the given pipe. ChildBrokerHost* pending_pipe_process = pending_child_connects_[pipe_id]; - EnsureProcessesConnected(pipe_process->GetProcessId(), - pending_pipe_process->GetProcessId()); - pending_pipe_process->ConnectMessagePipe( - pipe_id, pipe_process->GetProcessId()); - pipe_process->ConnectMessagePipe( - pipe_id, pending_pipe_process->GetProcessId()); + if (pending_pipe_process && pending_pipe_process->channel()) { + EnsureProcessesConnected(pipe_process->GetProcessId(), + pending_pipe_process->GetProcessId()); + pending_pipe_process->ConnectMessagePipe( + pipe_id, pipe_process->GetProcessId()); + pipe_process->ConnectMessagePipe( + pipe_id, pending_pipe_process->GetProcessId()); + } else { + pipe_process->PeerDied(pipe_id); + } pending_child_connects_.erase(pipe_id); return; } diff --git a/mojo/edk/system/child_broker.cc b/mojo/edk/system/child_broker.cc index 6903c82..85d9e52 100644 --- a/mojo/edk/system/child_broker.cc +++ b/mojo/edk/system/child_broker.cc @@ -220,6 +220,17 @@ void ChildBroker::OnReadMessage( CHECK(connected_pipes_.find(pipe) == connected_pipes_.end()); AttachMessagePipe(pipe, pipe_id, channels_[peer_pid]); } + } else if (type == PEER_DIED) { + DCHECK(!platform_handles); + const PeerDiedMessage* message = + static_cast<const PeerDiedMessage*>(message_view.bytes()); + + uint64_t pipe_id = message->pipe_id; + + CHECK(pending_connects_.find(pipe_id) != pending_connects_.end()); + MessagePipeDispatcher* pipe = pending_connects_[pipe_id]; + pending_connects_.erase(pipe_id); + pipe->OnError(ERROR_READ_SHUTDOWN); } else { NOTREACHED(); } diff --git a/mojo/edk/system/child_broker_host.cc b/mojo/edk/system/child_broker_host.cc index 20a73d9..bf594c1 100644 --- a/mojo/edk/system/child_broker_host.cc +++ b/mojo/edk/system/child_broker_host.cc @@ -105,6 +105,19 @@ void ChildBrokerHost::ConnectMessagePipe(uint64_t pipe_id, child_channel_->channel()->WriteMessage(std::move(message)); } +void ChildBrokerHost::PeerDied(uint64_t pipe_id) { + if (!child_channel_) + return; // Can happen at process shutdown on Windows. + PeerDiedMessage data; + memset(&data, 0, sizeof(data)); + data.type = PEER_DIED; + data.pipe_id = pipe_id; + scoped_ptr<MessageInTransit> message(new MessageInTransit( + MessageInTransit::Type::MESSAGE, sizeof(data), &data)); + message->set_route_id(kBrokerRouteId); + child_channel_->channel()->WriteMessage(std::move(message)); +} + ChildBrokerHost::~ChildBrokerHost() { DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); BrokerState::GetInstance()->ChildBrokerHostDestructed(this); diff --git a/mojo/edk/system/child_broker_host.h b/mojo/edk/system/child_broker_host.h index 943ff13..057b9e0 100644 --- a/mojo/edk/system/child_broker_host.h +++ b/mojo/edk/system/child_broker_host.h @@ -48,6 +48,10 @@ class MOJO_SYSTEM_IMPL_EXPORT ChildBrokerHost // be 0. void ConnectMessagePipe(uint64_t pipe_id, base::ProcessId process_id); + // Sends a message to the child process informing it that the peer process has + // died before it could connect. + void PeerDied(uint64_t pipe_id); + RoutedRawChannel* channel() { return child_channel_; } private: diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc index 119124a..11dc586 100644 --- a/mojo/edk/system/message_pipe_dispatcher.cc +++ b/mojo/edk/system/message_pipe_dispatcher.cc @@ -986,6 +986,10 @@ void MessagePipeDispatcher::OnError(Error error) { // Balance AddRef in CloseOnIO. call_release = true; } + } else if (!channel_ && !transferable_ && + non_transferable_state_ == WAITING_FOR_CONNECT_TO_CLOSE) { + // Balance AddRef in CloseOnIO. + call_release = true; } awakable_list_.AwakeForStateChange(GetHandleSignalsStateImplNoLock()); started_transport_.Release(); |