| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ipc/ipc_sync_message_filter.h" | 5 #include "ipc/ipc_sync_message_filter.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" |
| 11 #include "base/memory/ref_counted.h" |
| 12 #include "base/message_loop/message_loop.h" |
| 10 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 11 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
| 12 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 13 #include "ipc/ipc_channel.h" | 16 #include "ipc/ipc_channel.h" |
| 14 #include "ipc/ipc_sync_message.h" | 17 #include "ipc/ipc_sync_message.h" |
| 18 #include "ipc/mojo_event.h" |
| 19 #include "mojo/public/cpp/bindings/sync_handle_registry.h" |
| 15 | 20 |
| 16 namespace IPC { | 21 namespace IPC { |
| 17 | 22 |
| 23 namespace { |
| 24 |
| 25 // A generic callback used when watching handles synchronously. Sets |*signal| |
| 26 // to true. Also sets |*error| to true in case of an error. |
| 27 void OnSyncHandleReady(bool* signal, bool* error, MojoResult result) { |
| 28 *signal = true; |
| 29 *error = result != MOJO_RESULT_OK; |
| 30 } |
| 31 |
| 32 } // namespace |
| 33 |
| 18 bool SyncMessageFilter::Send(Message* message) { | 34 bool SyncMessageFilter::Send(Message* message) { |
| 19 if (!message->is_sync()) { | 35 if (!message->is_sync()) { |
| 20 { | 36 { |
| 21 base::AutoLock auto_lock(lock_); | 37 base::AutoLock auto_lock(lock_); |
| 22 if (!io_task_runner_.get()) { | 38 if (!io_task_runner_.get()) { |
| 23 pending_messages_.push_back(message); | 39 pending_messages_.emplace_back(base::WrapUnique(message)); |
| 24 return true; | 40 return true; |
| 25 } | 41 } |
| 26 } | 42 } |
| 27 io_task_runner_->PostTask( | 43 io_task_runner_->PostTask( |
| 28 FROM_HERE, | 44 FROM_HERE, |
| 29 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); | 45 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); |
| 30 return true; | 46 return true; |
| 31 } | 47 } |
| 32 | 48 |
| 33 base::WaitableEvent done_event( | 49 MojoEvent done_event; |
| 34 base::WaitableEvent::ResetPolicy::MANUAL, | |
| 35 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
| 36 PendingSyncMsg pending_message( | 50 PendingSyncMsg pending_message( |
| 37 SyncMessage::GetMessageId(*message), | 51 SyncMessage::GetMessageId(*message), |
| 38 static_cast<SyncMessage*>(message)->GetReplyDeserializer(), | 52 static_cast<SyncMessage*>(message)->GetReplyDeserializer(), |
| 39 &done_event); | 53 &done_event); |
| 40 | 54 |
| 41 { | 55 { |
| 42 base::AutoLock auto_lock(lock_); | 56 base::AutoLock auto_lock(lock_); |
| 43 // Can't use this class on the main thread or else it can lead to deadlocks. | 57 // Can't use this class on the main thread or else it can lead to deadlocks. |
| 44 // Also by definition, can't use this on IO thread since we're blocking it. | 58 // Also by definition, can't use this on IO thread since we're blocking it. |
| 45 if (base::ThreadTaskRunnerHandle::IsSet()) { | 59 if (base::ThreadTaskRunnerHandle::IsSet()) { |
| 46 DCHECK(base::ThreadTaskRunnerHandle::Get() != listener_task_runner_); | 60 DCHECK(base::ThreadTaskRunnerHandle::Get() != listener_task_runner_); |
| 47 DCHECK(base::ThreadTaskRunnerHandle::Get() != io_task_runner_); | 61 DCHECK(base::ThreadTaskRunnerHandle::Get() != io_task_runner_); |
| 48 } | 62 } |
| 49 pending_sync_messages_.insert(&pending_message); | 63 pending_sync_messages_.insert(&pending_message); |
| 50 | 64 |
| 51 if (io_task_runner_.get()) { | 65 if (io_task_runner_.get()) { |
| 52 io_task_runner_->PostTask( | 66 io_task_runner_->PostTask( |
| 53 FROM_HERE, | 67 FROM_HERE, |
| 54 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); | 68 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); |
| 55 } else { | 69 } else { |
| 56 pending_messages_.push_back(message); | 70 pending_messages_.emplace_back(base::WrapUnique(message)); |
| 57 } | 71 } |
| 58 } | 72 } |
| 59 | 73 |
| 60 base::WaitableEvent* events[2] = { shutdown_event_, &done_event }; | 74 bool done = false; |
| 61 if (base::WaitableEvent::WaitMany(events, 2) == 1) { | 75 bool shutdown = false; |
| 76 bool error = false; |
| 77 scoped_refptr<mojo::SyncHandleRegistry> registry = |
| 78 mojo::SyncHandleRegistry::current(); |
| 79 registry->RegisterHandle(shutdown_mojo_event_.GetHandle(), |
| 80 MOJO_HANDLE_SIGNAL_READABLE, |
| 81 base::Bind(&OnSyncHandleReady, &shutdown, &error)); |
| 82 registry->RegisterHandle(done_event.GetHandle(), |
| 83 MOJO_HANDLE_SIGNAL_READABLE, |
| 84 base::Bind(&OnSyncHandleReady, &done, &error)); |
| 85 |
| 86 const bool* stop_flags[] = { &done, &shutdown }; |
| 87 bool result = registry->WatchAllHandles(stop_flags, 2); |
| 88 DCHECK(result); |
| 89 DCHECK(!error); |
| 90 |
| 91 if (done) { |
| 62 TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), | 92 TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), |
| 63 "SyncMessageFilter::Send", &done_event); | 93 "SyncMessageFilter::Send", &done_event); |
| 64 } | 94 } |
| 95 registry->UnregisterHandle(shutdown_mojo_event_.GetHandle()); |
| 96 registry->UnregisterHandle(done_event.GetHandle()); |
| 65 | 97 |
| 66 { | 98 { |
| 67 base::AutoLock auto_lock(lock_); | 99 base::AutoLock auto_lock(lock_); |
| 68 delete pending_message.deserializer; | 100 delete pending_message.deserializer; |
| 69 pending_sync_messages_.erase(&pending_message); | 101 pending_sync_messages_.erase(&pending_message); |
| 70 } | 102 } |
| 71 | 103 |
| 72 return pending_message.send_result; | 104 return pending_message.send_result; |
| 73 } | 105 } |
| 74 | 106 |
| 75 void SyncMessageFilter::OnFilterAdded(Sender* sender) { | 107 void SyncMessageFilter::OnFilterAdded(Sender* sender) { |
| 76 std::vector<Message*> pending_messages; | 108 std::vector<std::unique_ptr<Message>> pending_messages; |
| 77 { | 109 { |
| 78 base::AutoLock auto_lock(lock_); | 110 base::AutoLock auto_lock(lock_); |
| 79 sender_ = sender; | 111 sender_ = sender; |
| 80 io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 112 io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 81 pending_messages_.release(&pending_messages); | 113 shutdown_watcher_.StartWatching( |
| 114 shutdown_event_, |
| 115 base::Bind(&SyncMessageFilter::OnShutdownEventSignaled, this)); |
| 116 std::swap(pending_messages_, pending_messages); |
| 82 } | 117 } |
| 83 for (auto* msg : pending_messages) | 118 for (auto& msg : pending_messages) |
| 84 SendOnIOThread(msg); | 119 SendOnIOThread(msg.release()); |
| 85 } | 120 } |
| 86 | 121 |
| 87 void SyncMessageFilter::OnChannelError() { | 122 void SyncMessageFilter::OnChannelError() { |
| 88 base::AutoLock auto_lock(lock_); | 123 base::AutoLock auto_lock(lock_); |
| 89 sender_ = NULL; | 124 sender_ = NULL; |
| 125 shutdown_watcher_.StopWatching(); |
| 90 SignalAllEvents(); | 126 SignalAllEvents(); |
| 91 } | 127 } |
| 92 | 128 |
| 93 void SyncMessageFilter::OnChannelClosing() { | 129 void SyncMessageFilter::OnChannelClosing() { |
| 94 base::AutoLock auto_lock(lock_); | 130 base::AutoLock auto_lock(lock_); |
| 95 sender_ = NULL; | 131 sender_ = NULL; |
| 132 shutdown_watcher_.StopWatching(); |
| 96 SignalAllEvents(); | 133 SignalAllEvents(); |
| 97 } | 134 } |
| 98 | 135 |
| 99 bool SyncMessageFilter::OnMessageReceived(const Message& message) { | 136 bool SyncMessageFilter::OnMessageReceived(const Message& message) { |
| 100 base::AutoLock auto_lock(lock_); | 137 base::AutoLock auto_lock(lock_); |
| 101 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); | 138 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); |
| 102 iter != pending_sync_messages_.end(); ++iter) { | 139 iter != pending_sync_messages_.end(); ++iter) { |
| 103 if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) { | 140 if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) { |
| 104 if (!message.is_reply_error()) { | 141 if (!message.is_reply_error()) { |
| 105 (*iter)->send_result = | 142 (*iter)->send_result = |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 lock_.AssertAcquired(); | 197 lock_.AssertAcquired(); |
| 161 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); | 198 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); |
| 162 iter != pending_sync_messages_.end(); ++iter) { | 199 iter != pending_sync_messages_.end(); ++iter) { |
| 163 TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), | 200 TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), |
| 164 "SyncMessageFilter::SignalAllEvents", | 201 "SyncMessageFilter::SignalAllEvents", |
| 165 (*iter)->done_event); | 202 (*iter)->done_event); |
| 166 (*iter)->done_event->Signal(); | 203 (*iter)->done_event->Signal(); |
| 167 } | 204 } |
| 168 } | 205 } |
| 169 | 206 |
| 207 void SyncMessageFilter::OnShutdownEventSignaled(base::WaitableEvent* event) { |
| 208 DCHECK_EQ(event, shutdown_event_); |
| 209 shutdown_mojo_event_.Signal(); |
| 210 } |
| 211 |
| 170 } // namespace IPC | 212 } // namespace IPC |
| OLD | NEW |