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

Unified Diff: ipc/ipc_channel_proxy.cc

Issue 183553004: Eliminate a potential race in IPC::ChannelProxy (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Clarify comment. Created 6 years, 10 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
« no previous file with comments | « ipc/ipc_channel_proxy.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ipc/ipc_channel_proxy.cc
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc
index 50431d575604c43045d174fa0800613bba17d463..b8bbe90aec34e6d822f15056715321df18c722da 100644
--- a/ipc/ipc_channel_proxy.cc
+++ b/ipc/ipc_channel_proxy.cc
@@ -156,7 +156,7 @@ void ChannelProxy::Context::ClearIPCTaskRunner() {
void ChannelProxy::Context::CreateChannel(const IPC::ChannelHandle& handle,
const Channel::Mode& mode) {
- DCHECK(channel_.get() == NULL);
+ DCHECK(!channel_);
channel_id_ = handle.name;
channel_.reset(new Channel(handle, mode, this));
}
@@ -196,17 +196,15 @@ bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
// Called on the IPC::Channel thread
void ChannelProxy::Context::OnChannelConnected(int32 peer_pid) {
+ // We cache off the peer_pid so it can be safely accessed from both threads.
+ peer_pid_ = channel_->peer_pid();
+
// Add any pending filters. This avoids a race condition where someone
// creates a ChannelProxy, calls AddFilter, and then right after starts the
// peer process. The IO thread could receive a message before the task to add
// the filter is run on the IO thread.
OnAddFilter();
- // We cache off the peer_pid so it can be safely accessed from both threads.
- peer_pid_ = channel_->peer_pid();
- for (size_t i = 0; i < filters_.size(); ++i)
- filters_[i]->OnChannelConnected(peer_pid);
-
// See above comment about using listener_task_runner_ here.
listener_task_runner_->PostTask(
FROM_HERE, base::Bind(&Context::OnDispatchConnected, this));
@@ -243,7 +241,7 @@ void ChannelProxy::Context::OnChannelOpened() {
void ChannelProxy::Context::OnChannelClosed() {
// It's okay for IPC::ChannelProxy::Close to be called more than once, which
// would result in this branch being taken.
- if (!channel_.get())
+ if (!channel_)
return;
for (size_t i = 0; i < filters_.size(); ++i) {
@@ -268,40 +266,57 @@ void ChannelProxy::Context::Clear() {
// Called on the IPC::Channel thread
void ChannelProxy::Context::OnSendMessage(scoped_ptr<Message> message) {
- if (!channel_.get()) {
- OnChannelClosed();
+ if (!channel_)
return;
dmichael (off chromium) 2014/02/28 23:25:47 There's no need to call OnChannelClosed; it's alre
- }
+
if (!channel_->Send(message.release()))
OnChannelError();
}
// Called on the IPC::Channel thread
void ChannelProxy::Context::OnAddFilter() {
+ // Our OnChannelConnected method has not yet been called, so we can't be
+ // sure that channel_ is valid yet. When OnChannelConnected *is* called,
+ // it invokes OnAddFilter, so any pending filter(s) will be added at that
+ // time.
+ if (peer_pid_ == base::kNullProcessId)
+ return;
+
std::vector<scoped_refptr<MessageFilter> > new_filters;
{
base::AutoLock auto_lock(pending_filters_lock_);
new_filters.swap(pending_filters_);
}
+ if (!channel_)
+ return; // The channel has been closed, so don't really add the filters.
jam 2014/03/03 16:27:03 can this condition really get hit since we're only
dmichael (off chromium) 2014/03/03 16:37:02 Good point, looks like it can't happen now. I'll
for (size_t i = 0; i < new_filters.size(); ++i) {
filters_.push_back(new_filters[i]);
message_filter_router_->AddFilter(new_filters[i].get());
- // If the channel has already been created, then we need to send this
- // message so that the filter gets access to the Channel.
- if (channel_.get())
- new_filters[i]->OnFilterAdded(channel_.get());
- // Ditto for if the channel has been connected.
- if (peer_pid_)
- new_filters[i]->OnChannelConnected(peer_pid_);
+ // The channel has already been created and connected, so we need to
+ // inform the filters right now.
+ new_filters[i]->OnFilterAdded(channel_.get());
+ new_filters[i]->OnChannelConnected(peer_pid_);
}
}
// Called on the IPC::Channel thread
void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) {
- if (!channel_.get())
+ if (peer_pid_ == base::kNullProcessId) {
+ // The channel is not yet connected, so any filters are still pending.
+ base::AutoLock auto_lock(pending_filters_lock_);
+ for (size_t i = 0; i < pending_filters_.size(); ++i) {
+ if (pending_filters_[i].get() == filter) {
+ filter->OnFilterRemoved();
+ pending_filters_.erase(pending_filters_.begin() + i);
+ return;
+ }
+ }
+ return;
+ }
+ if (!channel_)
return; // The filters have already been deleted.
message_filter_router_->RemoveFilter(filter);
« no previous file with comments | « ipc/ipc_channel_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698