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

Unified Diff: ipc/ipc_sync_channel.cc

Issue 271033: Multiple sync channels if used in the same listener thread could result in ca... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 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_sync_channel.h ('k') | ipc/ipc_sync_channel_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ipc/ipc_sync_channel.cc
===================================================================
--- ipc/ipc_sync_channel.cc (revision 28676)
+++ ipc/ipc_sync_channel.cc (working copy)
@@ -148,6 +148,14 @@
}
}
+ base::WaitableEventWatcher* top_send_done_watcher() {
+ return top_send_done_watcher_;
+ }
+
+ void set_top_send_done_watcher(base::WaitableEventWatcher* watcher) {
+ top_send_done_watcher_ = watcher;
+ }
+
private:
// See the comment in SyncChannel::SyncChannel for why this event is created
// as manual reset.
@@ -155,7 +163,8 @@
dispatch_event_(true, false),
listener_message_loop_(MessageLoop::current()),
task_pending_(false),
- listener_count_(0) {
+ listener_count_(0),
+ top_send_done_watcher_(NULL) {
}
// Holds information about a queued synchronous message or reply.
@@ -178,6 +187,11 @@
Lock message_lock_;
bool task_pending_;
int listener_count_;
+
+ // The current send done event watcher for this thread. Used to maintain
+ // a local global stack of send done watchers to ensure that nested sync
+ // message loops complete correctly.
+ base::WaitableEventWatcher* top_send_done_watcher_;
};
base::LazyInstance<base::ThreadLocalPointer<SyncChannel::ReceivedSyncMsgQueue> >
@@ -424,15 +438,39 @@
}
void SyncChannel::WaitForReplyWithNestedMessageLoop() {
- WaitableEvent* old_done_event = send_done_watcher_.GetWatchedEvent();
- send_done_watcher_.StopWatching();
- send_done_watcher_.StartWatching(sync_context()->GetSendDoneEvent(), this);
+ base::WaitableEventWatcher send_done_watcher;
+
+ ReceivedSyncMsgQueue* sync_msg_queue = sync_context()->received_sync_msgs();
+ DCHECK(sync_msg_queue != NULL);
+
+ base::WaitableEventWatcher* old_send_done_event_watcher =
+ sync_msg_queue->top_send_done_watcher();
+
+ base::WaitableEventWatcher::Delegate* old_delegate = NULL;
+ base::WaitableEvent* old_event = NULL;
+
+ // Maintain a local global stack of send done delegates to ensure that
+ // nested sync calls complete in the correct sequence, i.e. the
+ // outermost call completes first, etc.
+ if (old_send_done_event_watcher) {
+ old_delegate = old_send_done_event_watcher->delegate();
+ old_event = old_send_done_event_watcher->GetWatchedEvent();
+ old_send_done_event_watcher->StopWatching();
+ }
+
+ sync_msg_queue->set_top_send_done_watcher(&send_done_watcher);
+
+ send_done_watcher.StartWatching(sync_context()->GetSendDoneEvent(), this);
bool old_state = MessageLoop::current()->NestableTasksAllowed();
+
MessageLoop::current()->SetNestableTasksAllowed(true);
MessageLoop::current()->Run();
MessageLoop::current()->SetNestableTasksAllowed(old_state);
- if (old_done_event)
- send_done_watcher_.StartWatching(old_done_event, this);
+
+ sync_msg_queue->set_top_send_done_watcher(old_send_done_event_watcher);
+ if (old_send_done_event_watcher) {
+ old_send_done_event_watcher->StartWatching(old_event, old_delegate);
+ }
}
void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) {
« no previous file with comments | « ipc/ipc_sync_channel.h ('k') | ipc/ipc_sync_channel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698