15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_channel.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event_watcher.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_task_runner_handle.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_local.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_logging.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::WaitableEvent; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When we're blocked in a Send(), we need to process incoming synchronous 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// messages right away because it could be blocking our reply (either 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// directly from the same object we're calling, or indirectly through one or 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// more other channels). That means that in SyncContext's OnMessageReceived, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we need to process sync message right away if we're blocked. However a 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple check isn't sufficient, because the listener thread can be in the 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// process of calling Send. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To work around this, when SyncChannel filters a sync message, it sets 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an event that the listener thread waits on during its Send() call. This 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allows us to dispatch incoming sync messages when blocked. The race 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// condition is handled because if Send is in the process of being called, it 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will check the event. In case the listener thread isn't sending a message, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we queue a task on the listener thread to dispatch the received messages. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The messages are stored in this queue object that's shared among all 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SyncChannel objects on the same thread (since one object can receive a 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sync message while another one is blocked). 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncChannel::ReceivedSyncMsgQueue : 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::RefCountedThreadSafe<ReceivedSyncMsgQueue> { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the ReceivedSyncMsgQueue instance for this thread, creating one 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if necessary. Call RemoveContext on the same thread when done. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ReceivedSyncMsgQueue* AddContext() { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want one ReceivedSyncMsgQueue per listener thread (i.e. since multiple 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SyncChannel objects can block the same thread). 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReceivedSyncMsgQueue* rv = lazy_tls_ptr_.Pointer()->Get(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!rv) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = new ReceivedSyncMsgQueue(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReceivedSyncMsgQueue::lazy_tls_ptr_.Pointer()->Set(rv); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv->listener_count_++; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on IPC thread when a synchronous message or reply arrives. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void QueueMessage(const Message& msg, SyncChannel::SyncContext* context) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_task_pending; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(message_lock_); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) was_task_pending = task_pending_; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_pending_ = true; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We set the event in case the listener thread is blocked (or is about 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to). In case it's not, the PostTask dispatches the messages. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_queue_.push_back(QueuedMessage(new Message(msg), context)); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_queue_version_++; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dispatch_event_.Signal(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!was_task_pending) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_task_runner_->PostTask( 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&ReceivedSyncMsgQueue::DispatchMessagesTask, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, scoped_refptr<SyncContext>(context))); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void QueueReply(const Message &msg, SyncChannel::SyncContext* context) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_replies_.push_back(QueuedMessage(new Message(msg), context)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on the listener's thread to process any queues synchronous 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // messages. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DispatchMessagesTask(SyncContext* context) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(message_lock_); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_pending_ = false; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->DispatchMessages(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DispatchMessages(SyncContext* dispatching_context) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool first_time = true; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 expected_version = 0; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncMessageQueue::iterator it; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Message* message = NULL; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SyncChannel::SyncContext> context; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(message_lock_); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first_time || message_queue_version_ != expected_version) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it = message_queue_.begin(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_time = false; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; it != message_queue_.end(); it++) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int message_group = it->context->restrict_dispatch_group(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message_group == kRestrictDispatchGroup_None || 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_group == dispatching_context->restrict_dispatch_group()) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message = it->message; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context = it->context; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it = message_queue_.erase(it); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_queue_version_++; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expected_version = message_queue_version_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message == NULL) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->OnDispatchMessage(*message); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete message; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SyncChannel calls this in its destructor. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveContext(SyncContext* context) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(message_lock_); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncMessageQueue::iterator iter = message_queue_.begin(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iter != message_queue_.end()) { 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (iter->context.get() == context) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete iter->message; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter = message_queue_.erase(iter); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_queue_version_++; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter++; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--listener_count_ == 0) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(lazy_tls_ptr_.Pointer()->Get()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lazy_tls_ptr_.Pointer()->Set(NULL); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* dispatch_event() { return &dispatch_event_; } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SingleThreadTaskRunner* listener_task_runner() { 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return listener_task_runner_.get(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Holds a pointer to the per-thread ReceivedSyncMsgQueue object. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static base::LazyInstance<base::ThreadLocalPointer<ReceivedSyncMsgQueue> > 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lazy_tls_ptr_; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on the ipc thread to check if we can unblock any current Send() 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calls based on a queued reply. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DispatchReplies() { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < received_replies_.size(); ++i) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Message* message = received_replies_[i].message; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (received_replies_[i].context->TryToUnblockListener(message)) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete message; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_replies_.erase(received_replies_.begin() + i); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEventWatcher* top_send_done_watcher() { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return top_send_done_watcher_; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_top_send_done_watcher(base::WaitableEventWatcher* watcher) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_send_done_watcher_ = watcher; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<ReceivedSyncMsgQueue>; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See the comment in SyncChannel::SyncChannel for why this event is created 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as manual reset. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReceivedSyncMsgQueue() : 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_queue_version_(0), 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dispatch_event_(true, false), 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_task_runner_(base::ThreadTaskRunnerHandle::Get()), 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) task_pending_(false), 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) listener_count_(0), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_send_done_watcher_(NULL) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ReceivedSyncMsgQueue() {} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Holds information about a queued synchronous message or reply. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct QueuedMessage { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueuedMessage(Message* m, SyncContext* c) : message(m), context(c) { } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Message* message; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SyncChannel::SyncContext> context; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::list<QueuedMessage> SyncMessageQueue; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncMessageQueue message_queue_; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 message_queue_version_; // Used to signal DispatchMessages to rescan 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<QueuedMessage> received_replies_; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set when we got a synchronous message that we must respond to as the 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sender needs its reply before it can reply to our original synchronous 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent dispatch_event_; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> listener_task_runner_; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock message_lock_; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool task_pending_; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int listener_count_; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current send done event watcher for this thread. Used to maintain 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a local global stack of send done watchers to ensure that nested sync 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message loops complete correctly. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEventWatcher* top_send_done_watcher_; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<base::ThreadLocalPointer<SyncChannel::ReceivedSyncMsgQueue> > 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_ = 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncChannel::SyncContext::SyncContext( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Listener* listener, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SingleThreadTaskRunner* ipc_task_runner, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* shutdown_event) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ChannelProxy::Context(listener, ipc_task_runner), 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_sync_msgs_(ReceivedSyncMsgQueue::AddContext()), 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_event_(shutdown_event), 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restrict_dispatch_group_(kRestrictDispatchGroup_None) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncChannel::SyncContext::~SyncContext() { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!deserializers_.empty()) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pop(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds information about an outgoing sync message to the context so that 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we know how to deserialize the reply. Returns a handle that's set when 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the reply has arrived. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::Push(SyncMessage* sync_msg) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the tracking information for this message. This object is stored 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by value since all members are pointers that are cheap to copy. These 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointers are cleaned up in the Pop() function. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The event is created as manual reset because in between Signal and 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnObjectSignalled, another Send can happen which would stop the watcher 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from being called. The event would get watched later, when the nested 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send completes, so the event will need to remain set. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingSyncMsg pending(SyncMessage::GetMessageId(*sync_msg), 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_msg->GetReplyDeserializer(), 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new WaitableEvent(true, false)); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(deserializers_lock_); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deserializers_.push_back(pending); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncChannel::SyncContext::Pop() { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(deserializers_lock_); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingSyncMsg msg = deserializers_.back(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete msg.deserializer; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete msg.done_event; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.done_event = NULL; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deserializers_.pop_back(); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = msg.send_result; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We got a reply to a synchronous Send() call that's blocking the listener 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread. However, further down the call stack there could be another 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blocking Send() call, whose reply we received after we made this last 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send() call. So check if we have any queued replies available that 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can now unblock the listener thread. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ipc_task_runner()->PostTask( 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&ReceivedSyncMsgQueue::DispatchReplies, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_sync_msgs_.get())); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WaitableEvent* SyncChannel::SyncContext::GetSendDoneEvent() { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(deserializers_lock_); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return deserializers_.back().done_event; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WaitableEvent* SyncChannel::SyncContext::GetDispatchEvent() { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return received_sync_msgs_->dispatch_event(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::DispatchMessages() { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_sync_msgs_->DispatchMessages(this); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncChannel::SyncContext::TryToUnblockListener(const Message* msg) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(deserializers_lock_); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (deserializers_.empty() || 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !SyncMessage::IsMessageReplyTo(*msg, deserializers_.back().id)) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(bauerb): Remove logging once investigation of http://crbug.com/141055 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has finished. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!msg->is_reply_error()) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool send_result = deserializers_.back().deserializer-> 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SerializeOutputParameters(*msg); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deserializers_.back().send_result = send_result; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG_IF(1, !send_result) << "Couldn't deserialize reply message"; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Received error reply"; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deserializers_.back().done_event->Signal(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::Clear() { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingSends(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_sync_msgs_->RemoveContext(this); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Context::Clear(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncChannel::SyncContext::OnMessageReceived(const Message& msg) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Give the filters a chance at processing this message. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TryFilters(msg)) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TryToUnblockListener(&msg)) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (msg.is_reply()) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_sync_msgs_->QueueReply(msg, this); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (msg.should_unblock()) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_sync_msgs_->QueueMessage(msg, this); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Context::OnMessageReceivedNoFilter(msg); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::OnChannelError() { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingSends(); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_watcher_.StopWatching(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Context::OnChannelError(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::OnChannelOpened() { 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shutdown_watcher_.StartWatching( 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shutdown_event_, 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SyncChannel::SyncContext::OnWaitableEventSignaled, 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Context::OnChannelOpened(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::OnChannelClosed() { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingSends(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_watcher_.StopWatching(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Context::OnChannelClosed(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::OnSendTimeout(int message_id) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(deserializers_lock_); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingSyncMessageQueue::iterator iter; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Send timeout"; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->id == message_id) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->done_event->Signal(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::CancelPendingSends() { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(deserializers_lock_); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingSyncMessageQueue::iterator iter; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(bauerb): Remove once http://crbug/141055 is fixed. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Canceling pending sends"; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->done_event->Signal(); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SyncContext::OnWaitableEventSignaled(WaitableEvent* event) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event == shutdown_event_) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process shut down before we can get a reply to a synchronous message. 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel pending Send calls, which will end up setting the send done event. 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingSends(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We got the reply, timed out or the process shutdown. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(GetSendDoneEvent(), event); 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->QuitNow(); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::WaitableEventWatcher::EventCallback 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyncChannel::SyncContext::MakeWaitableEventCallback() { 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::Bind(&SyncChannel::SyncContext::OnWaitableEventSignaled, this); 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_ptr<SyncChannel> SyncChannel::Create( 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPC::ChannelHandle& channel_handle, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Channel::Mode mode, 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Listener* listener, 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SingleThreadTaskRunner* ipc_task_runner, 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool create_pipe_now, 41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::WaitableEvent* shutdown_event) { 41546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SyncChannel> channel = 41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Create(listener, ipc_task_runner, shutdown_event); 41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) channel->Init(channel_handle, mode, create_pipe_now); 41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return channel.Pass(); 41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 42146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_ptr<SyncChannel> SyncChannel::Create( 42346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Listener* listener, 42446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::SingleThreadTaskRunner* ipc_task_runner, 42546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) WaitableEvent* shutdown_event) { 42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return make_scoped_ptr( 42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new SyncChannel(listener, ipc_task_runner, shutdown_event)); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncChannel::SyncChannel( 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Listener* listener, 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SingleThreadTaskRunner* ipc_task_runner, 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* shutdown_event) 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : ChannelProxy(new SyncContext(listener, ipc_task_runner, shutdown_event)) { 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // The current (listener) thread must be distinct from the IPC thread, or else 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // sending synchronous messages will deadlock. 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_NE(ipc_task_runner, base::ThreadTaskRunnerHandle::Get()); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartWatching(); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncChannel::~SyncChannel() { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::SetRestrictDispatchChannelGroup(int group) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_context()->set_restrict_dispatch_group(group); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncChannel::Send(Message* message) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef IPC_MESSAGE_LOG_ENABLED 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Logging* logger = Logging::GetInstance(); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logger->GetMessageText(message->type(), &name, message, NULL); 453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TRACE_EVENT1("ipc", "SyncChannel::Send", "name", name); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TRACE_EVENT2("ipc", "SyncChannel::Send", 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "class", IPC_MESSAGE_ID_CLASS(message->type()), 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "line", IPC_MESSAGE_ID_LINE(message->type())); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!message->is_sync()) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelProxy::Send(message); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // *this* might get deleted in WaitForReply. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SyncContext> context(sync_context()); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (context->shutdown_event()->IsSignaled()) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "shutdown event is signaled"; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete message; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncMessage* sync_msg = static_cast<SyncMessage*>(message); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->Push(sync_msg); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* pump_messages_event = sync_msg->pump_messages_event(); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelProxy::Send(message); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for reply, or for any other incoming synchronous messages. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // *this* might get deleted, so only call static functions at this point. 480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WaitForReply(context.get(), pump_messages_event); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context->Pop(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::WaitForReply( 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncContext* context, WaitableEvent* pump_messages_event) { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->DispatchMessages(); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* objects[] = { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->GetDispatchEvent(), 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->GetSendDoneEvent(), 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pump_messages_event 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned count = pump_messages_event ? 3: 2; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t result = WaitableEvent::WaitMany(objects, count); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0 /* dispatch event */) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're waiting for a reply, but we received a blocking synchronous 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call. We must process it or otherwise a deadlock might occur. 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->GetDispatchEvent()->Reset(); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->DispatchMessages(); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 2 /* pump_messages_event */) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitForReplyWithNestedMessageLoop(context); // Run a nested message loop. 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::WaitForReplyWithNestedMessageLoop(SyncContext* context) { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEventWatcher send_done_watcher; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReceivedSyncMsgQueue* sync_msg_queue = context->received_sync_msgs(); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(sync_msg_queue != NULL); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEventWatcher* old_send_done_event_watcher = 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_msg_queue->top_send_done_watcher(); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WaitableEventWatcher::EventCallback old_callback; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent* old_event = NULL; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maintain a local global stack of send done delegates to ensure that 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // nested sync calls complete in the correct sequence, i.e. the 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // outermost call completes first, etc. 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_send_done_event_watcher) { 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_callback = old_send_done_event_watcher->callback(); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_event = old_send_done_event_watcher->GetWatchedEvent(); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_send_done_event_watcher->StopWatching(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_msg_queue->set_top_send_done_watcher(&send_done_watcher); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) send_done_watcher.StartWatching(context->GetSendDoneEvent(), 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context->MakeWaitableEventCallback()); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::ScopedNestableTaskAllower allow( 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()); 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Run(); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_msg_queue->set_top_send_done_watcher(old_send_done_event_watcher); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_send_done_event_watcher && old_event) { 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_send_done_event_watcher->StartWatching(old_event, old_callback); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::OnWaitableEventSignaled(WaitableEvent* event) { 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(event == sync_context()->GetDispatchEvent()); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The call to DispatchMessages might delete this object, so reregister 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the object watcher first. 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->Reset(); 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_watcher_.StartWatching(event, dispatch_watcher_callback_); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_context()->DispatchMessages(); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncChannel::StartWatching() { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ideally we only want to watch this object when running a nested message 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loop. However, we don't know when it exits if there's another nested 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message loop running under it or not, so we wouldn't know whether to 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stop or keep watching. So we always watch it, and create the event as 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // manual reset since the object watcher might otherwise reset the event 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when we're doing a WaitMany. 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_watcher_callback_ = 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SyncChannel::OnWaitableEventSignaled, 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this)); 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_watcher_.StartWatching(sync_context()->GetDispatchEvent(), 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dispatch_watcher_callback_); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace IPC 574