blob: 842e04e74c6f33038a7415c205af3df1c8c53137 [file] [log] [blame]
[email protected]522cc10d2012-01-11 22:39:541// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]946d1b22009-07-22 23:57:215#include "ipc/ipc_sync_channel.h"
initial.commit09911bf2008-07-26 23:55:296
avi246998d82015-12-22 02:39:047#include <stddef.h>
8#include <stdint.h>
danakj03de39b22016-04-23 04:21:099
dchenge48600452015-12-28 02:24:5010#include <utility>
avi246998d82015-12-22 02:39:0411
[email protected]72b6f8e22011-11-12 21:16:4112#include "base/bind.h"
[email protected]f886b7bf2008-09-10 10:54:0613#include "base/lazy_instance.h"
[email protected]c62dd9d2011-09-21 18:05:4114#include "base/location.h"
initial.commit09911bf2008-07-26 23:55:2915#include "base/logging.h"
rockot3c236292016-07-07 20:26:0216#include "base/macros.h"
danakj03de39b22016-04-23 04:21:0917#include "base/memory/ptr_util.h"
fdoray6d056ff2016-07-04 21:56:4218#include "base/run_loop.h"
[email protected]44f9c952011-01-02 06:05:3919#include "base/synchronization/waitable_event.h"
[email protected]b2432302012-07-02 21:15:5220#include "base/threading/thread_local.h"
gabf08ccc02016-05-11 18:51:1121#include "base/threading/thread_task_runner_handle.h"
primiano7182d7b2015-01-30 18:02:0322#include "base/trace_event/trace_event.h"
[email protected]64860882014-08-04 23:44:1723#include "ipc/ipc_channel_factory.h"
[email protected]60b2c61f2012-08-22 22:39:5724#include "ipc/ipc_logging.h"
25#include "ipc/ipc_message_macros.h"
[email protected]946d1b22009-07-22 23:57:2126#include "ipc/ipc_sync_message.h"
rockotb62e2e32017-03-24 18:36:4427#include "mojo/public/cpp/bindings/sync_event_watcher.h"
initial.commit09911bf2008-07-26 23:55:2928
[email protected]1c4947f2009-01-15 22:25:1129using base::WaitableEvent;
initial.commit09911bf2008-07-26 23:55:2930
31namespace IPC {
rockot3c236292016-07-07 20:26:0232
33namespace {
34
35// A generic callback used when watching handles synchronously. Sets |*signal|
rockotb62e2e32017-03-24 18:36:4436// to true.
37void OnEventReady(bool* signal) {
rockot3c236292016-07-07 20:26:0238 *signal = true;
rockot3c236292016-07-07 20:26:0239}
40
rockotb62e2e32017-03-24 18:36:4441base::LazyInstance<std::unique_ptr<base::WaitableEvent>>::Leaky
42 g_pump_messages_event = LAZY_INSTANCE_INITIALIZER;
rockot3c236292016-07-07 20:26:0243
44} // namespace
45
initial.commit09911bf2008-07-26 23:55:2946// When we're blocked in a Send(), we need to process incoming synchronous
47// messages right away because it could be blocking our reply (either
48// directly from the same object we're calling, or indirectly through one or
49// more other channels). That means that in SyncContext's OnMessageReceived,
50// we need to process sync message right away if we're blocked. However a
51// simple check isn't sufficient, because the listener thread can be in the
52// process of calling Send.
53// To work around this, when SyncChannel filters a sync message, it sets
54// an event that the listener thread waits on during its Send() call. This
55// allows us to dispatch incoming sync messages when blocked. The race
56// condition is handled because if Send is in the process of being called, it
57// will check the event. In case the listener thread isn't sending a message,
58// we queue a task on the listener thread to dispatch the received messages.
59// The messages are stored in this queue object that's shared among all
60// SyncChannel objects on the same thread (since one object can receive a
61// sync message while another one is blocked).
62
initial.commit09911bf2008-07-26 23:55:2963class SyncChannel::ReceivedSyncMsgQueue :
64 public base::RefCountedThreadSafe<ReceivedSyncMsgQueue> {
65 public:
rockotb62e2e32017-03-24 18:36:4466 // SyncChannel::WaitForReplyWithNestedMessageLoop may be re-entered, i.e. we
67 // may nest waiting message loops arbitrarily deep on the SyncChannel's
68 // thread. Every such operation has a corresponding WaitableEvent to be
69 // watched which, when signalled for IPC completion, breaks out of the loop.
70 // A reference to the innermost (i.e. topmost) watcher is held in
71 // |ReceivedSyncMsgQueue::top_send_done_event_watcher_|.
72 //
73 // NestedSendDoneWatcher provides a simple scoper which is used by
74 // WaitForReplyWithNestedMessageLoop to begin watching a new local "send done"
75 // event, preserving the previous topmost state on the local stack until the
76 // new inner loop is broken. If yet another subsequent nested loop is started
77 // therein the process is repeated again in the new inner stack frame, and so
78 // on.
79 //
80 // When this object is destroyed on stack unwind, the previous topmost state
81 // is swapped back into |ReceivedSyncMsgQueue::top_send_done_event_watcher_|,
82 // and its watch is resumed immediately.
83 class NestedSendDoneWatcher {
84 public:
85 NestedSendDoneWatcher(SyncChannel::SyncContext* context,
86 base::RunLoop* run_loop)
87 : sync_msg_queue_(context->received_sync_msgs()),
88 outer_state_(sync_msg_queue_->top_send_done_event_watcher_),
89 event_(context->GetSendDoneEvent()),
90 callback_(
tzik130cfd0c2017-04-18 03:49:0591 base::BindOnce(&SyncChannel::SyncContext::OnSendDoneEventSignaled,
92 context,
93 run_loop)) {
rockotb62e2e32017-03-24 18:36:4494 sync_msg_queue_->top_send_done_event_watcher_ = this;
95 if (outer_state_)
96 outer_state_->StopWatching();
97 StartWatching();
98 }
99
100 ~NestedSendDoneWatcher() {
101 sync_msg_queue_->top_send_done_event_watcher_ = outer_state_;
102 if (outer_state_)
103 outer_state_->StartWatching();
104 }
105
106 private:
tzik130cfd0c2017-04-18 03:49:05107 void Run(WaitableEvent* event) {
108 DCHECK(callback_);
109 std::move(callback_).Run(event);
110 }
111
112 void StartWatching() {
113 watcher_.StartWatching(event_, base::BindOnce(&NestedSendDoneWatcher::Run,
114 base::Unretained(this)));
115 }
116
rockotb62e2e32017-03-24 18:36:44117 void StopWatching() { watcher_.StopWatching(); }
118
119 ReceivedSyncMsgQueue* const sync_msg_queue_;
120 NestedSendDoneWatcher* const outer_state_;
121
122 base::WaitableEvent* const event_;
tzik130cfd0c2017-04-18 03:49:05123 base::WaitableEventWatcher::EventCallback callback_;
rockotb62e2e32017-03-24 18:36:44124 base::WaitableEventWatcher watcher_;
125
126 DISALLOW_COPY_AND_ASSIGN(NestedSendDoneWatcher);
127 };
128
[email protected]3cdb7af812008-10-24 19:21:13129 // Returns the ReceivedSyncMsgQueue instance for this thread, creating one
[email protected]d3ae7a072008-12-05 20:27:20130 // if necessary. Call RemoveContext on the same thread when done.
131 static ReceivedSyncMsgQueue* AddContext() {
[email protected]3cdb7af812008-10-24 19:21:13132 // We want one ReceivedSyncMsgQueue per listener thread (i.e. since multiple
133 // SyncChannel objects can block the same thread).
134 ReceivedSyncMsgQueue* rv = lazy_tls_ptr_.Pointer()->Get();
135 if (!rv) {
136 rv = new ReceivedSyncMsgQueue();
137 ReceivedSyncMsgQueue::lazy_tls_ptr_.Pointer()->Set(rv);
138 }
139 rv->listener_count_++;
140 return rv;
initial.commit09911bf2008-07-26 23:55:29141 }
142
rockot9abe09b2016-08-02 20:57:34143 // Prevents messages from being dispatched immediately when the dispatch event
144 // is signaled. Instead, |*dispatch_flag| will be set.
145 void BlockDispatch(bool* dispatch_flag) { dispatch_flag_ = dispatch_flag; }
146
147 // Allows messages to be dispatched immediately when the dispatch event is
148 // signaled.
149 void UnblockDispatch() { dispatch_flag_ = nullptr; }
150
initial.commit09911bf2008-07-26 23:55:29151 // Called on IPC thread when a synchronous message or reply arrives.
[email protected]d3ae7a072008-12-05 20:27:20152 void QueueMessage(const Message& msg, SyncChannel::SyncContext* context) {
initial.commit09911bf2008-07-26 23:55:29153 bool was_task_pending;
154 {
[email protected]20305ec2011-01-21 04:55:52155 base::AutoLock auto_lock(message_lock_);
initial.commit09911bf2008-07-26 23:55:29156
157 was_task_pending = task_pending_;
158 task_pending_ = true;
159
160 // We set the event in case the listener thread is blocked (or is about
161 // to). In case it's not, the PostTask dispatches the messages.
[email protected]d3ae7a072008-12-05 20:27:20162 message_queue_.push_back(QueuedMessage(new Message(msg), context));
[email protected]522cc10d2012-01-11 22:39:54163 message_queue_version_++;
initial.commit09911bf2008-07-26 23:55:29164 }
165
[email protected]1c4947f2009-01-15 22:25:11166 dispatch_event_.Signal();
initial.commit09911bf2008-07-26 23:55:29167 if (!was_task_pending) {
[email protected]b2432302012-07-02 21:15:52168 listener_task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41169 FROM_HERE, base::Bind(&ReceivedSyncMsgQueue::DispatchMessagesTask,
vmpstra34d11322016-03-21 20:28:47170 this, base::RetainedRef(context)));
initial.commit09911bf2008-07-26 23:55:29171 }
172 }
173
174 void QueueReply(const Message &msg, SyncChannel::SyncContext* context) {
[email protected]d3ae7a072008-12-05 20:27:20175 received_replies_.push_back(QueuedMessage(new Message(msg), context));
initial.commit09911bf2008-07-26 23:55:29176 }
177
[email protected]d3ae7a072008-12-05 20:27:20178 // Called on the listener's thread to process any queues synchronous
initial.commit09911bf2008-07-26 23:55:29179 // messages.
[email protected]54af05f2011-04-08 03:38:21180 void DispatchMessagesTask(SyncContext* context) {
initial.commit09911bf2008-07-26 23:55:29181 {
[email protected]20305ec2011-01-21 04:55:52182 base::AutoLock auto_lock(message_lock_);
initial.commit09911bf2008-07-26 23:55:29183 task_pending_ = false;
184 }
[email protected]54af05f2011-04-08 03:38:21185 context->DispatchMessages();
initial.commit09911bf2008-07-26 23:55:29186 }
187
rockot9abe09b2016-08-02 20:57:34188 // Dispatches any queued incoming sync messages. If |dispatching_context| is
189 // not null, messages which target a restricted dispatch channel will only be
190 // dispatched if |dispatching_context| belongs to the same restricted dispatch
191 // group as that channel. If |dispatching_context| is null, all queued
192 // messages are dispatched.
[email protected]54af05f2011-04-08 03:38:21193 void DispatchMessages(SyncContext* dispatching_context) {
[email protected]522cc10d2012-01-11 22:39:54194 bool first_time = true;
tfarina10a5c062015-09-04 18:47:57195 uint32_t expected_version = 0;
[email protected]522cc10d2012-01-11 22:39:54196 SyncMessageQueue::iterator it;
initial.commit09911bf2008-07-26 23:55:29197 while (true) {
rockot9abe09b2016-08-02 20:57:34198 Message* message = nullptr;
[email protected]d3ae7a072008-12-05 20:27:20199 scoped_refptr<SyncChannel::SyncContext> context;
initial.commit09911bf2008-07-26 23:55:29200 {
[email protected]20305ec2011-01-21 04:55:52201 base::AutoLock auto_lock(message_lock_);
[email protected]522cc10d2012-01-11 22:39:54202 if (first_time || message_queue_version_ != expected_version) {
203 it = message_queue_.begin();
204 first_time = false;
[email protected]54af05f2011-04-08 03:38:21205 }
[email protected]522cc10d2012-01-11 22:39:54206 for (; it != message_queue_.end(); it++) {
[email protected]298ee7d2012-03-30 21:29:30207 int message_group = it->context->restrict_dispatch_group();
rockot9abe09b2016-08-02 20:57:34208 if (!dispatching_context ||
209 message_group == kRestrictDispatchGroup_None ||
[email protected]298ee7d2012-03-30 21:29:30210 message_group == dispatching_context->restrict_dispatch_group()) {
[email protected]522cc10d2012-01-11 22:39:54211 message = it->message;
212 context = it->context;
213 it = message_queue_.erase(it);
214 message_queue_version_++;
215 expected_version = message_queue_version_;
216 break;
217 }
218 }
219 }
initial.commit09911bf2008-07-26 23:55:29220
rockot9abe09b2016-08-02 20:57:34221 if (message == nullptr)
[email protected]522cc10d2012-01-11 22:39:54222 break;
223 context->OnDispatchMessage(*message);
224 delete message;
initial.commit09911bf2008-07-26 23:55:29225 }
226 }
227
initial.commit09911bf2008-07-26 23:55:29228 // SyncChannel calls this in its destructor.
[email protected]d3ae7a072008-12-05 20:27:20229 void RemoveContext(SyncContext* context) {
[email protected]20305ec2011-01-21 04:55:52230 base::AutoLock auto_lock(message_lock_);
initial.commit09911bf2008-07-26 23:55:29231
[email protected]d3ae7a072008-12-05 20:27:20232 SyncMessageQueue::iterator iter = message_queue_.begin();
233 while (iter != message_queue_.end()) {
[email protected]17571642013-06-01 04:11:27234 if (iter->context.get() == context) {
[email protected]d3ae7a072008-12-05 20:27:20235 delete iter->message;
236 iter = message_queue_.erase(iter);
[email protected]522cc10d2012-01-11 22:39:54237 message_queue_version_++;
initial.commit09911bf2008-07-26 23:55:29238 } else {
[email protected]d3ae7a072008-12-05 20:27:20239 iter++;
initial.commit09911bf2008-07-26 23:55:29240 }
initial.commit09911bf2008-07-26 23:55:29241 }
[email protected]3cdb7af812008-10-24 19:21:13242
243 if (--listener_count_ == 0) {
244 DCHECK(lazy_tls_ptr_.Pointer()->Get());
rockot9abe09b2016-08-02 20:57:34245 lazy_tls_ptr_.Pointer()->Set(nullptr);
246 sync_dispatch_watcher_.reset();
[email protected]3cdb7af812008-10-24 19:21:13247 }
initial.commit09911bf2008-07-26 23:55:29248 }
249
rockotb62e2e32017-03-24 18:36:44250 base::WaitableEvent* dispatch_event() { return &dispatch_event_; }
[email protected]b2432302012-07-02 21:15:52251 base::SingleThreadTaskRunner* listener_task_runner() {
[email protected]17571642013-06-01 04:11:27252 return listener_task_runner_.get();
[email protected]92bf9062011-05-02 18:00:49253 }
initial.commit09911bf2008-07-26 23:55:29254
[email protected]f886b7bf2008-09-10 10:54:06255 // Holds a pointer to the per-thread ReceivedSyncMsgQueue object.
scottmg5e65e3a2017-03-08 08:48:46256 static base::LazyInstance<base::ThreadLocalPointer<ReceivedSyncMsgQueue>>::
257 DestructorAtExit lazy_tls_ptr_;
[email protected]f886b7bf2008-09-10 10:54:06258
initial.commit09911bf2008-07-26 23:55:29259 // Called on the ipc thread to check if we can unblock any current Send()
260 // calls based on a queued reply.
261 void DispatchReplies() {
initial.commit09911bf2008-07-26 23:55:29262 for (size_t i = 0; i < received_replies_.size(); ++i) {
263 Message* message = received_replies_[i].message;
[email protected]3cdb7af812008-10-24 19:21:13264 if (received_replies_[i].context->TryToUnblockListener(message)) {
initial.commit09911bf2008-07-26 23:55:29265 delete message;
266 received_replies_.erase(received_replies_.begin() + i);
267 return;
268 }
269 }
270 }
271
[email protected]63a7bb82008-10-25 00:46:00272 private:
[email protected]877d55d2009-11-05 21:53:08273 friend class base::RefCountedThreadSafe<ReceivedSyncMsgQueue>;
274
[email protected]4df10d612008-11-12 00:38:26275 // See the comment in SyncChannel::SyncChannel for why this event is created
276 // as manual reset.
gab90c2c5c2016-06-01 20:34:06277 ReceivedSyncMsgQueue()
278 : message_queue_version_(0),
rockotb62e2e32017-03-24 18:36:44279 dispatch_event_(base::WaitableEvent::ResetPolicy::MANUAL,
280 base::WaitableEvent::InitialState::NOT_SIGNALED),
gab90c2c5c2016-06-01 20:34:06281 listener_task_runner_(base::ThreadTaskRunnerHandle::Get()),
rockotb62e2e32017-03-24 18:36:44282 sync_dispatch_watcher_(base::MakeUnique<mojo::SyncEventWatcher>(
283 &dispatch_event_,
284 base::Bind(&ReceivedSyncMsgQueue::OnDispatchEventReady,
285 base::Unretained(this)))) {
rockot9abe09b2016-08-02 20:57:34286 sync_dispatch_watcher_->AllowWokenUpBySyncWatchOnSameThread();
287 }
[email protected]63a7bb82008-10-25 00:46:00288
[email protected]877d55d2009-11-05 21:53:08289 ~ReceivedSyncMsgQueue() {}
290
rockotb62e2e32017-03-24 18:36:44291 void OnDispatchEventReady() {
rockot9abe09b2016-08-02 20:57:34292 if (dispatch_flag_) {
293 *dispatch_flag_ = true;
294 return;
295 }
296
297 // We were woken up during a sync wait, but no specific SyncChannel is
298 // currently waiting. i.e., some other Mojo interface on this thread is
299 // waiting for a response. Since we don't support anything analogous to
300 // restricted dispatch on Mojo interfaces, in this case it's safe to
301 // dispatch sync messages for any context.
302 DispatchMessages(nullptr);
303 }
304
[email protected]d3ae7a072008-12-05 20:27:20305 // Holds information about a queued synchronous message or reply.
306 struct QueuedMessage {
307 QueuedMessage(Message* m, SyncContext* c) : message(m), context(c) { }
initial.commit09911bf2008-07-26 23:55:29308 Message* message;
309 scoped_refptr<SyncChannel::SyncContext> context;
310 };
311
[email protected]522cc10d2012-01-11 22:39:54312 typedef std::list<QueuedMessage> SyncMessageQueue;
[email protected]1c4947f2009-01-15 22:25:11313 SyncMessageQueue message_queue_;
rockotb62e2e32017-03-24 18:36:44314
315 // Used to signal DispatchMessages to rescan
316 uint32_t message_queue_version_ = 0;
[email protected]d3ae7a072008-12-05 20:27:20317
318 std::vector<QueuedMessage> received_replies_;
[email protected]3cdb7af812008-10-24 19:21:13319
rockot3c236292016-07-07 20:26:02320 // Signaled when we get a synchronous message that we must respond to, as the
[email protected]3cdb7af812008-10-24 19:21:13321 // sender needs its reply before it can reply to our original synchronous
322 // message.
rockotb62e2e32017-03-24 18:36:44323 base::WaitableEvent dispatch_event_;
[email protected]b2432302012-07-02 21:15:52324 scoped_refptr<base::SingleThreadTaskRunner> listener_task_runner_;
[email protected]20305ec2011-01-21 04:55:52325 base::Lock message_lock_;
rockotb62e2e32017-03-24 18:36:44326 bool task_pending_ = false;
327 int listener_count_ = 0;
[email protected]ac0efda2009-10-14 16:22:02328
rockotb62e2e32017-03-24 18:36:44329 // The current NestedSendDoneWatcher for this thread, if we're currently
330 // in a SyncChannel::WaitForReplyWithNestedMessageLoop. See
331 // NestedSendDoneWatcher comments for more details.
332 NestedSendDoneWatcher* top_send_done_event_watcher_ = nullptr;
rockot9abe09b2016-08-02 20:57:34333
334 // If not null, the address of a flag to set when the dispatch event signals,
335 // in lieu of actually dispatching messages. This is used by
336 // SyncChannel::WaitForReply to restrict the scope of queued messages we're
337 // allowed to process while it's waiting.
338 bool* dispatch_flag_ = nullptr;
339
340 // Watches |dispatch_event_| during all sync handle watches on this thread.
rockotb62e2e32017-03-24 18:36:44341 std::unique_ptr<mojo::SyncEventWatcher> sync_dispatch_watcher_;
initial.commit09911bf2008-07-26 23:55:29342};
343
scottmg5e65e3a2017-03-08 08:48:46344base::LazyInstance<base::ThreadLocalPointer<
345 SyncChannel::ReceivedSyncMsgQueue>>::DestructorAtExit
[email protected]6de0fd1d2011-11-15 13:31:49346 SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_ =
347 LAZY_INSTANCE_INITIALIZER;
initial.commit09911bf2008-07-26 23:55:29348
349SyncChannel::SyncContext::SyncContext(
[email protected]b7f59e822012-06-29 22:05:26350 Listener* listener,
dchengfd033702014-08-28 16:59:29351 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
[email protected]1c4947f2009-01-15 22:25:11352 WaitableEvent* shutdown_event)
[email protected]b2432302012-07-02 21:15:52353 : ChannelProxy::Context(listener, ipc_task_runner),
[email protected]1c4947f2009-01-15 22:25:11354 received_sync_msgs_(ReceivedSyncMsgQueue::AddContext()),
[email protected]54af05f2011-04-08 03:38:21355 shutdown_event_(shutdown_event),
[email protected]298ee7d2012-03-30 21:29:30356 restrict_dispatch_group_(kRestrictDispatchGroup_None) {
initial.commit09911bf2008-07-26 23:55:29357}
358
rockotb62e2e32017-03-24 18:36:44359void SyncChannel::SyncContext::OnSendDoneEventSignaled(
360 base::RunLoop* nested_loop,
361 base::WaitableEvent* event) {
362 DCHECK_EQ(GetSendDoneEvent(), event);
363 nested_loop->Quit();
364}
365
initial.commit09911bf2008-07-26 23:55:29366SyncChannel::SyncContext::~SyncContext() {
367 while (!deserializers_.empty())
[email protected]3cdb7af812008-10-24 19:21:13368 Pop();
initial.commit09911bf2008-07-26 23:55:29369}
370
371// Adds information about an outgoing sync message to the context so that
rockot3c236292016-07-07 20:26:02372// we know how to deserialize the reply. Returns |true| if the message was added
373// to the context or |false| if it was rejected (e.g. due to shutdown.)
374bool SyncChannel::SyncContext::Push(SyncMessage* sync_msg) {
[email protected]4a180a52011-04-15 19:07:43375 // Create the tracking information for this message. This object is stored
376 // by value since all members are pointers that are cheap to copy. These
377 // pointers are cleaned up in the Pop() function.
378 //
[email protected]1c4947f2009-01-15 22:25:11379 // The event is created as manual reset because in between Signal and
[email protected]4df10d612008-11-12 00:38:26380 // OnObjectSignalled, another Send can happen which would stop the watcher
381 // from being called. The event would get watched later, when the nested
382 // Send completes, so the event will need to remain set.
rockot3c236292016-07-07 20:26:02383 base::AutoLock auto_lock(deserializers_lock_);
384 if (reject_new_deserializers_)
385 return false;
gab90c2c5c2016-06-01 20:34:06386 PendingSyncMsg pending(
387 SyncMessage::GetMessageId(*sync_msg), sync_msg->GetReplyDeserializer(),
rockotb62e2e32017-03-24 18:36:44388 new base::WaitableEvent(base::WaitableEvent::ResetPolicy::MANUAL,
389 base::WaitableEvent::InitialState::NOT_SIGNALED));
[email protected]3cdb7af812008-10-24 19:21:13390 deserializers_.push_back(pending);
rockot3c236292016-07-07 20:26:02391 return true;
initial.commit09911bf2008-07-26 23:55:29392}
393
[email protected]3cdb7af812008-10-24 19:21:13394bool SyncChannel::SyncContext::Pop() {
[email protected]63a7bb82008-10-25 00:46:00395 bool result;
396 {
[email protected]20305ec2011-01-21 04:55:52397 base::AutoLock auto_lock(deserializers_lock_);
[email protected]63a7bb82008-10-25 00:46:00398 PendingSyncMsg msg = deserializers_.back();
399 delete msg.deserializer;
[email protected]1c4947f2009-01-15 22:25:11400 delete msg.done_event;
rockot3c236292016-07-07 20:26:02401 msg.done_event = nullptr;
[email protected]63a7bb82008-10-25 00:46:00402 deserializers_.pop_back();
403 result = msg.send_result;
404 }
405
406 // We got a reply to a synchronous Send() call that's blocking the listener
407 // thread. However, further down the call stack there could be another
408 // blocking Send() call, whose reply we received after we made this last
409 // Send() call. So check if we have any queued replies available that
410 // can now unblock the listener thread.
[email protected]b2432302012-07-02 21:15:52411 ipc_task_runner()->PostTask(
[email protected]72b6f8e22011-11-12 21:16:41412 FROM_HERE, base::Bind(&ReceivedSyncMsgQueue::DispatchReplies,
tzik07cace42016-09-01 04:21:25413 received_sync_msgs_));
[email protected]63a7bb82008-10-25 00:46:00414
415 return result;
[email protected]3cdb7af812008-10-24 19:21:13416}
417
rockotb62e2e32017-03-24 18:36:44418base::WaitableEvent* SyncChannel::SyncContext::GetSendDoneEvent() {
[email protected]20305ec2011-01-21 04:55:52419 base::AutoLock auto_lock(deserializers_lock_);
[email protected]3cdb7af812008-10-24 19:21:13420 return deserializers_.back().done_event;
421}
422
rockotb62e2e32017-03-24 18:36:44423base::WaitableEvent* SyncChannel::SyncContext::GetDispatchEvent() {
[email protected]3cdb7af812008-10-24 19:21:13424 return received_sync_msgs_->dispatch_event();
initial.commit09911bf2008-07-26 23:55:29425}
426
427void SyncChannel::SyncContext::DispatchMessages() {
[email protected]54af05f2011-04-08 03:38:21428 received_sync_msgs_->DispatchMessages(this);
initial.commit09911bf2008-07-26 23:55:29429}
430
[email protected]3cdb7af812008-10-24 19:21:13431bool SyncChannel::SyncContext::TryToUnblockListener(const Message* msg) {
[email protected]20305ec2011-01-21 04:55:52432 base::AutoLock auto_lock(deserializers_lock_);
[email protected]63a7bb82008-10-25 00:46:00433 if (deserializers_.empty() ||
434 !SyncMessage::IsMessageReplyTo(*msg, deserializers_.back().id)) {
435 return false;
[email protected]3cdb7af812008-10-24 19:21:13436 }
initial.commit09911bf2008-07-26 23:55:29437
[email protected]63a7bb82008-10-25 00:46:00438 if (!msg->is_reply_error()) {
[email protected]211142cd2012-08-13 09:41:19439 bool send_result = deserializers_.back().deserializer->
[email protected]63a7bb82008-10-25 00:46:00440 SerializeOutputParameters(*msg);
[email protected]211142cd2012-08-13 09:41:19441 deserializers_.back().send_result = send_result;
bauerb3e9be732015-11-03 18:17:47442 DVLOG_IF(1, !send_result) << "Couldn't deserialize reply message";
[email protected]211142cd2012-08-13 09:41:19443 } else {
bauerb3e9be732015-11-03 18:17:47444 DVLOG(1) << "Received error reply";
[email protected]63a7bb82008-10-25 00:46:00445 }
tzika08b2fd2016-03-30 02:32:59446
rockotb62e2e32017-03-24 18:36:44447 base::WaitableEvent* done_event = deserializers_.back().done_event;
tzika08b2fd2016-03-30 02:32:59448 TRACE_EVENT_FLOW_BEGIN0(
449 TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
450 "SyncChannel::SyncContext::TryToUnblockListener", done_event);
451
452 done_event->Signal();
initial.commit09911bf2008-07-26 23:55:29453
[email protected]3cdb7af812008-10-24 19:21:13454 return true;
initial.commit09911bf2008-07-26 23:55:29455}
456
[email protected]3cdb7af812008-10-24 19:21:13457void SyncChannel::SyncContext::Clear() {
458 CancelPendingSends();
[email protected]d3ae7a072008-12-05 20:27:20459 received_sync_msgs_->RemoveContext(this);
[email protected]3cdb7af812008-10-24 19:21:13460 Context::Clear();
461}
462
[email protected]a95986a82010-12-24 06:19:28463bool SyncChannel::SyncContext::OnMessageReceived(const Message& msg) {
[email protected]d65cab7a2008-08-12 01:25:41464 // Give the filters a chance at processing this message.
465 if (TryFilters(msg))
[email protected]a95986a82010-12-24 06:19:28466 return true;
[email protected]d65cab7a2008-08-12 01:25:41467
[email protected]3cdb7af812008-10-24 19:21:13468 if (TryToUnblockListener(&msg))
[email protected]a95986a82010-12-24 06:19:28469 return true;
initial.commit09911bf2008-07-26 23:55:29470
[email protected]9134cce6d2012-04-10 20:07:53471 if (msg.is_reply()) {
472 received_sync_msgs_->QueueReply(msg, this);
[email protected]a95986a82010-12-24 06:19:28473 return true;
initial.commit09911bf2008-07-26 23:55:29474 }
475
[email protected]9134cce6d2012-04-10 20:07:53476 if (msg.should_unblock()) {
477 received_sync_msgs_->QueueMessage(msg, this);
[email protected]a95986a82010-12-24 06:19:28478 return true;
initial.commit09911bf2008-07-26 23:55:29479 }
480
[email protected]3cdb7af812008-10-24 19:21:13481 return Context::OnMessageReceivedNoFilter(msg);
initial.commit09911bf2008-07-26 23:55:29482}
483
initial.commit09911bf2008-07-26 23:55:29484void SyncChannel::SyncContext::OnChannelError() {
[email protected]3cdb7af812008-10-24 19:21:13485 CancelPendingSends();
[email protected]a4f822702009-02-06 00:44:53486 shutdown_watcher_.StopWatching();
initial.commit09911bf2008-07-26 23:55:29487 Context::OnChannelError();
488}
489
rockot10188752016-09-08 18:24:56490void SyncChannel::SyncContext::OnChannelOpened() {
[email protected]329be052013-02-04 18:14:28491 shutdown_watcher_.StartWatching(
492 shutdown_event_,
rockot3c236292016-07-07 20:26:02493 base::Bind(&SyncChannel::SyncContext::OnShutdownEventSignaled,
[email protected]329be052013-02-04 18:14:28494 base::Unretained(this)));
rockot10188752016-09-08 18:24:56495 Context::OnChannelOpened();
initial.commit09911bf2008-07-26 23:55:29496}
497
[email protected]3cdb7af812008-10-24 19:21:13498void SyncChannel::SyncContext::OnChannelClosed() {
[email protected]87339f02010-09-02 21:45:50499 CancelPendingSends();
[email protected]3cdb7af812008-10-24 19:21:13500 shutdown_watcher_.StopWatching();
501 Context::OnChannelClosed();
502}
503
[email protected]3cdb7af812008-10-24 19:21:13504void SyncChannel::SyncContext::CancelPendingSends() {
[email protected]20305ec2011-01-21 04:55:52505 base::AutoLock auto_lock(deserializers_lock_);
rockot3c236292016-07-07 20:26:02506 reject_new_deserializers_ = true;
[email protected]3cdb7af812008-10-24 19:21:13507 PendingSyncMessageQueue::iterator iter;
bauerb3e9be732015-11-03 18:17:47508 DVLOG(1) << "Canceling pending sends";
tzika08b2fd2016-03-30 02:32:59509 for (iter = deserializers_.begin(); iter != deserializers_.end(); iter++) {
510 TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
511 "SyncChannel::SyncContext::CancelPendingSends",
512 iter->done_event);
[email protected]1c4947f2009-01-15 22:25:11513 iter->done_event->Signal();
tzika08b2fd2016-03-30 02:32:59514 }
[email protected]3cdb7af812008-10-24 19:21:13515}
516
rockot3c236292016-07-07 20:26:02517void SyncChannel::SyncContext::OnShutdownEventSignaled(WaitableEvent* event) {
518 DCHECK_EQ(event, shutdown_event_);
[email protected]3cdb7af812008-10-24 19:21:13519
rockot3c236292016-07-07 20:26:02520 // Process shut down before we can get a reply to a synchronous message.
521 // Cancel pending Send calls, which will end up setting the send done event.
522 CancelPendingSends();
[email protected]329be052013-02-04 18:14:28523}
[email protected]3cdb7af812008-10-24 19:21:13524
[email protected]fca876a12014-06-05 16:15:38525// static
danakj03de39b22016-04-23 04:21:09526std::unique_ptr<SyncChannel> SyncChannel::Create(
[email protected]42ce94e2010-12-08 19:28:09527 const IPC::ChannelHandle& channel_handle,
[email protected]3b0e4662014-06-02 20:29:30528 Channel::Mode mode,
[email protected]b7f59e822012-06-29 22:05:26529 Listener* listener,
dchengfd033702014-08-28 16:59:29530 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
[email protected]4b580bf2010-12-02 19:16:07531 bool create_pipe_now,
erikchen30dc2812015-09-24 03:26:38532 base::WaitableEvent* shutdown_event) {
danakj03de39b22016-04-23 04:21:09533 std::unique_ptr<SyncChannel> channel =
[email protected]fca876a12014-06-05 16:15:38534 Create(listener, ipc_task_runner, shutdown_event);
erikchen30dc2812015-09-24 03:26:38535 channel->Init(channel_handle, mode, create_pipe_now);
dchenge48600452015-12-28 02:24:50536 return channel;
[email protected]fca876a12014-06-05 16:15:38537}
538
539// static
danakj03de39b22016-04-23 04:21:09540std::unique_ptr<SyncChannel> SyncChannel::Create(
541 std::unique_ptr<ChannelFactory> factory,
[email protected]64860882014-08-04 23:44:17542 Listener* listener,
dchengfd033702014-08-28 16:59:29543 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
[email protected]64860882014-08-04 23:44:17544 bool create_pipe_now,
545 base::WaitableEvent* shutdown_event) {
danakj03de39b22016-04-23 04:21:09546 std::unique_ptr<SyncChannel> channel =
[email protected]64860882014-08-04 23:44:17547 Create(listener, ipc_task_runner, shutdown_event);
dchenge48600452015-12-28 02:24:50548 channel->Init(std::move(factory), create_pipe_now);
549 return channel;
[email protected]64860882014-08-04 23:44:17550}
551
552// static
danakj03de39b22016-04-23 04:21:09553std::unique_ptr<SyncChannel> SyncChannel::Create(
[email protected]fca876a12014-06-05 16:15:38554 Listener* listener,
dchengfd033702014-08-28 16:59:29555 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
[email protected]fca876a12014-06-05 16:15:38556 WaitableEvent* shutdown_event) {
danakj03de39b22016-04-23 04:21:09557 return base::WrapUnique(
[email protected]fca876a12014-06-05 16:15:38558 new SyncChannel(listener, ipc_task_runner, shutdown_event));
[email protected]952394af2011-11-16 01:06:46559}
560
561SyncChannel::SyncChannel(
[email protected]b7f59e822012-06-29 22:05:26562 Listener* listener,
dchengfd033702014-08-28 16:59:29563 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
[email protected]952394af2011-11-16 01:06:46564 WaitableEvent* shutdown_event)
rockot3c236292016-07-07 20:26:02565 : ChannelProxy(new SyncContext(listener, ipc_task_runner, shutdown_event)),
rockotb62e2e32017-03-24 18:36:44566 sync_handle_registry_(mojo::SyncHandleRegistry::current()) {
[email protected]1f9cf472014-04-17 05:07:18567 // The current (listener) thread must be distinct from the IPC thread, or else
568 // sending synchronous messages will deadlock.
dchengff04843f2014-09-03 18:01:16569 DCHECK_NE(ipc_task_runner.get(), base::ThreadTaskRunnerHandle::Get().get());
[email protected]952394af2011-11-16 01:06:46570 StartWatching();
initial.commit09911bf2008-07-26 23:55:29571}
572
573SyncChannel::~SyncChannel() {
initial.commit09911bf2008-07-26 23:55:29574}
575
[email protected]298ee7d2012-03-30 21:29:30576void SyncChannel::SetRestrictDispatchChannelGroup(int group) {
577 sync_context()->set_restrict_dispatch_group(group);
[email protected]54af05f2011-04-08 03:38:21578}
579
rockotac64ae92f2015-08-06 00:32:29580scoped_refptr<SyncMessageFilter> SyncChannel::CreateSyncMessageFilter() {
581 scoped_refptr<SyncMessageFilter> filter = new SyncMessageFilter(
rockotb97e3d32016-09-16 17:39:03582 sync_context()->shutdown_event());
rockotac64ae92f2015-08-06 00:32:29583 AddFilter(filter.get());
rockot29ade1b2015-08-07 06:23:59584 if (!did_init())
585 pre_init_sync_message_filters_.push_back(filter);
rockotac64ae92f2015-08-06 00:32:29586 return filter;
587}
588
[email protected]3cdb7af812008-10-24 19:21:13589bool SyncChannel::Send(Message* message) {
jwdc1028922017-03-28 21:12:31590#ifdef IPC_MESSAGE_LOG_ENABLED
[email protected]60b2c61f2012-08-22 22:39:57591 std::string name;
rockot9abe09b2016-08-02 20:57:34592 Logging::GetInstance()->GetMessageText(
593 message->type(), &name, message, nullptr);
[email protected]d6cbf052014-05-02 21:29:24594 TRACE_EVENT1("ipc", "SyncChannel::Send", "name", name);
[email protected]60b2c61f2012-08-22 22:39:57595#else
[email protected]d6cbf052014-05-02 21:29:24596 TRACE_EVENT2("ipc", "SyncChannel::Send",
[email protected]60b2c61f2012-08-22 22:39:57597 "class", IPC_MESSAGE_ID_CLASS(message->type()),
598 "line", IPC_MESSAGE_ID_LINE(message->type()));
599#endif
[email protected]3cdb7af812008-10-24 19:21:13600 if (!message->is_sync()) {
601 ChannelProxy::Send(message);
602 return true;
initial.commit09911bf2008-07-26 23:55:29603 }
604
rockot3c236292016-07-07 20:26:02605 SyncMessage* sync_msg = static_cast<SyncMessage*>(message);
606 bool pump_messages = sync_msg->ShouldPumpMessages();
607
[email protected]3cdb7af812008-10-24 19:21:13608 // *this* might get deleted in WaitForReply.
609 scoped_refptr<SyncContext> context(sync_context());
rockot3c236292016-07-07 20:26:02610 if (!context->Push(sync_msg)) {
611 DVLOG(1) << "Channel is shutting down. Dropping sync message.";
[email protected]3cdb7af812008-10-24 19:21:13612 delete message;
613 return false;
614 }
615
initial.commit09911bf2008-07-26 23:55:29616 ChannelProxy::Send(message);
initial.commit09911bf2008-07-26 23:55:29617
[email protected]3cdb7af812008-10-24 19:21:13618 // Wait for reply, or for any other incoming synchronous messages.
rockot9abe09b2016-08-02 20:57:34619 // |this| might get deleted, so only call static functions at this point.
rockot3c236292016-07-07 20:26:02620 scoped_refptr<mojo::SyncHandleRegistry> registry = sync_handle_registry_;
621 WaitForReply(registry.get(), context.get(), pump_messages);
initial.commit09911bf2008-07-26 23:55:29622
tzika08b2fd2016-03-30 02:32:59623 TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
624 "SyncChannel::Send", context->GetSendDoneEvent());
625
[email protected]3cdb7af812008-10-24 19:21:13626 return context->Pop();
initial.commit09911bf2008-07-26 23:55:29627}
628
rockot3c236292016-07-07 20:26:02629void SyncChannel::WaitForReply(mojo::SyncHandleRegistry* registry,
630 SyncContext* context,
631 bool pump_messages) {
[email protected]54af05f2011-04-08 03:38:21632 context->DispatchMessages();
rockot64e65de2016-06-21 20:17:49633
rockotb62e2e32017-03-24 18:36:44634 base::WaitableEvent* pump_messages_event = nullptr;
635 if (pump_messages) {
636 if (!g_pump_messages_event.Get()) {
637 g_pump_messages_event.Get() = base::MakeUnique<base::WaitableEvent>(
638 base::WaitableEvent::ResetPolicy::MANUAL,
639 base::WaitableEvent::InitialState::SIGNALED);
640 }
641 pump_messages_event = g_pump_messages_event.Get().get();
642 }
rockot3c236292016-07-07 20:26:02643
644 while (true) {
645 bool dispatch = false;
646 bool send_done = false;
647 bool should_pump_messages = false;
rockotb62e2e32017-03-24 18:36:44648 bool registered = registry->RegisterEvent(
649 context->GetSendDoneEvent(), base::Bind(&OnEventReady, &send_done));
rockot9abe09b2016-08-02 20:57:34650 DCHECK(registered);
rockotb62e2e32017-03-24 18:36:44651
rockot3c236292016-07-07 20:26:02652 if (pump_messages_event) {
rockotb62e2e32017-03-24 18:36:44653 registered = registry->RegisterEvent(
654 pump_messages_event,
655 base::Bind(&OnEventReady, &should_pump_messages));
rockot9abe09b2016-08-02 20:57:34656 DCHECK(registered);
rockot3c236292016-07-07 20:26:02657 }
658
659 const bool* stop_flags[] = { &dispatch, &send_done, &should_pump_messages };
rockot9abe09b2016-08-02 20:57:34660 context->received_sync_msgs()->BlockDispatch(&dispatch);
rockotb62e2e32017-03-24 18:36:44661 registry->Wait(stop_flags, 3);
rockot9abe09b2016-08-02 20:57:34662 context->received_sync_msgs()->UnblockDispatch();
rockot3c236292016-07-07 20:26:02663
rockotb62e2e32017-03-24 18:36:44664 registry->UnregisterEvent(context->GetSendDoneEvent());
rockot3c236292016-07-07 20:26:02665 if (pump_messages_event)
rockotb62e2e32017-03-24 18:36:44666 registry->UnregisterEvent(pump_messages_event);
rockot3c236292016-07-07 20:26:02667
668 if (dispatch) {
rockot9abe09b2016-08-02 20:57:34669 // We're waiting for a reply, but we received a blocking synchronous call.
670 // We must process it to avoid potential deadlocks.
[email protected]9eec2252009-12-01 02:34:18671 context->GetDispatchEvent()->Reset();
672 context->DispatchMessages();
[email protected]3cdb7af812008-10-24 19:21:13673 continue;
674 }
675
rockot3c236292016-07-07 20:26:02676 if (should_pump_messages)
[email protected]9eec2252009-12-01 02:34:18677 WaitForReplyWithNestedMessageLoop(context); // Run a nested message loop.
[email protected]3cdb7af812008-10-24 19:21:13678
679 break;
680 }
681}
682
[email protected]9eec2252009-12-01 02:34:18683void SyncChannel::WaitForReplyWithNestedMessageLoop(SyncContext* context) {
rockotb62e2e32017-03-24 18:36:44684 base::MessageLoop::ScopedNestableTaskAllower allow(
685 base::MessageLoop::current());
686 base::RunLoop nested_loop;
687 ReceivedSyncMsgQueue::NestedSendDoneWatcher watcher(context, &nested_loop);
688 nested_loop.Run();
[email protected]3cdb7af812008-10-24 19:21:13689}
690
rockotb62e2e32017-03-24 18:36:44691void SyncChannel::OnDispatchEventSignaled(base::WaitableEvent* event) {
692 DCHECK_EQ(sync_context()->GetDispatchEvent(), event);
yzshen1bd23702016-11-30 21:54:51693 sync_context()->GetDispatchEvent()->Reset();
rockotb62e2e32017-03-24 18:36:44694
695 StartWatching();
696
697 // NOTE: May delete |this|.
yzshen1bd23702016-11-30 21:54:51698 sync_context()->DispatchMessages();
initial.commit09911bf2008-07-26 23:55:29699}
700
[email protected]952394af2011-11-16 01:06:46701void SyncChannel::StartWatching() {
rockot9abe09b2016-08-02 20:57:34702 // |dispatch_watcher_| watches the event asynchronously, only dispatching
703 // messages once the listener thread is unblocked and pumping its task queue.
704 // The ReceivedSyncMsgQueue also watches this event and may dispatch
705 // immediately if woken up by a message which it's allowed to dispatch.
rockotb62e2e32017-03-24 18:36:44706 dispatch_watcher_.StartWatching(
707 sync_context()->GetDispatchEvent(),
708 base::Bind(&SyncChannel::OnDispatchEventSignaled,
709 base::Unretained(this)));
[email protected]952394af2011-11-16 01:06:46710}
711
rockot29ade1b2015-08-07 06:23:59712void SyncChannel::OnChannelInit() {
rockot29ade1b2015-08-07 06:23:59713 pre_init_sync_message_filters_.clear();
714}
715
initial.commit09911bf2008-07-26 23:55:29716} // namespace IPC