diff options
author | jhorwich@chromium.org <jhorwich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-11 22:39:54 +0000 |
---|---|---|
committer | jhorwich@chromium.org <jhorwich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-11 22:39:54 +0000 |
commit | 522cc10d714c4a2e519176a8f24d2549820f63dc (patch) | |
tree | 1860802c1776ec2669811866f9be16f0cfd1275e /ipc/ipc_sync_channel.cc | |
parent | 76b2482e4bb8586807d92025b942817030b3690d (diff) | |
download | chromium_src-522cc10d714c4a2e519176a8f24d2549820f63dc.zip chromium_src-522cc10d714c4a2e519176a8f24d2549820f63dc.tar.gz chromium_src-522cc10d714c4a2e519176a8f24d2549820f63dc.tar.bz2 |
Reimplement ReceivedSyncMsgQueue::DispatchMessages
Implementation of IPC::SyncChannel::ReceivedSyncMsgQueue::DispatchMessages that
does not hold any messages in a local stack-frame's delayed_queue, which was
causing me to see an inbound sync message from a plugin not dispatched while
the renderer was waiting for replies from the plugin. This was causing the
plugin and renderer to deadlock waiting for each other.
BUG=108491
TEST=Run Pepperized O3D and observe for tab hangs
TEST=Run ipc_tests unittests
Review URL: http://codereview.chromium.org/9022038
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117309 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ipc/ipc_sync_channel.cc')
-rw-r--r-- | ipc/ipc_sync_channel.cc | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc index f3c5384..74d9744 100644 --- a/ipc/ipc_sync_channel.cc +++ b/ipc/ipc_sync_channel.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -64,6 +64,7 @@ class SyncChannel::ReceivedSyncMsgQueue : // We set the event in case the listener thread is blocked (or is about // to). In case it's not, the PostTask dispatches the messages. message_queue_.push_back(QueuedMessage(new Message(msg), context)); + message_queue_version_++; } dispatch_event_.Signal(); @@ -89,27 +90,35 @@ class SyncChannel::ReceivedSyncMsgQueue : } void DispatchMessages(SyncContext* dispatching_context) { - SyncMessageQueue delayed_queue; + bool first_time = true; + uint32 expected_version = 0; + SyncMessageQueue::iterator it; while (true) { - Message* message; + Message* message = NULL; scoped_refptr<SyncChannel::SyncContext> context; { base::AutoLock auto_lock(message_lock_); - if (message_queue_.empty()) { - message_queue_ = delayed_queue; - break; + if (first_time || message_queue_version_ != expected_version) { + it = message_queue_.begin(); + first_time = false; + } + for (; it != message_queue_.end(); it++) { + if (!it->context->restrict_dispatch() || + it->context == dispatching_context) { + message = it->message; + context = it->context; + it = message_queue_.erase(it); + message_queue_version_++; + expected_version = message_queue_version_; + break; + } } - - message = message_queue_.front().message; - context = message_queue_.front().context; - message_queue_.pop_front(); - } - if (context->restrict_dispatch() && context != dispatching_context) { - delayed_queue.push_back(QueuedMessage(message, context)); - } else { - context->OnDispatchMessage(*message); - delete message; } + + if (message == NULL) + break; + context->OnDispatchMessage(*message); + delete message; } } @@ -122,6 +131,7 @@ class SyncChannel::ReceivedSyncMsgQueue : if (iter->context == context) { delete iter->message; iter = message_queue_.erase(iter); + message_queue_version_++; } else { iter++; } @@ -169,6 +179,7 @@ class SyncChannel::ReceivedSyncMsgQueue : // See the comment in SyncChannel::SyncChannel for why this event is created // as manual reset. ReceivedSyncMsgQueue() : + message_queue_version_(0), dispatch_event_(true, false), listener_message_loop_(base::MessageLoopProxy::current()), task_pending_(false), @@ -185,8 +196,9 @@ class SyncChannel::ReceivedSyncMsgQueue : scoped_refptr<SyncChannel::SyncContext> context; }; - typedef std::deque<QueuedMessage> SyncMessageQueue; + typedef std::list<QueuedMessage> SyncMessageQueue; SyncMessageQueue message_queue_; + uint32 message_queue_version_; // Used to signal DispatchMessages to rescan std::vector<QueuedMessage> received_replies_; |