| 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" | |
| 13 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
| 14 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
| 15 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 16 #include "ipc/ipc_channel.h" | 13 #include "ipc/ipc_channel.h" |
| 17 #include "ipc/ipc_sync_message.h" | 14 #include "ipc/ipc_sync_message.h" |
| 18 #include "ipc/mojo_event.h" | |
| 19 #include "mojo/public/cpp/bindings/sync_handle_registry.h" | |
| 20 | 15 |
| 21 namespace IPC { | 16 namespace IPC { |
| 22 | 17 |
| 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 | |
| 34 bool SyncMessageFilter::Send(Message* message) { | 18 bool SyncMessageFilter::Send(Message* message) { |
| 35 if (!message->is_sync()) { | 19 if (!message->is_sync()) { |
| 36 { | 20 { |
| 37 base::AutoLock auto_lock(lock_); | 21 base::AutoLock auto_lock(lock_); |
| 38 if (sender_ && is_channel_send_thread_safe_) { | 22 if (sender_ && is_channel_send_thread_safe_) { |
| 39 sender_->Send(message); | 23 sender_->Send(message); |
| 40 return true; | 24 return true; |
| 41 } else if (!io_task_runner_.get()) { | 25 } else if (!io_task_runner_.get()) { |
| 42 pending_messages_.emplace_back(base::WrapUnique(message)); | 26 pending_messages_.push_back(message); |
| 43 return true; | 27 return true; |
| 44 } | 28 } |
| 45 } | 29 } |
| 46 io_task_runner_->PostTask( | 30 io_task_runner_->PostTask( |
| 47 FROM_HERE, | 31 FROM_HERE, |
| 48 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); | 32 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); |
| 49 return true; | 33 return true; |
| 50 } | 34 } |
| 51 | 35 |
| 52 MojoEvent done_event; | 36 base::WaitableEvent done_event( |
| 37 base::WaitableEvent::ResetPolicy::MANUAL, |
| 38 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 53 PendingSyncMsg pending_message( | 39 PendingSyncMsg pending_message( |
| 54 SyncMessage::GetMessageId(*message), | 40 SyncMessage::GetMessageId(*message), |
| 55 static_cast<SyncMessage*>(message)->GetReplyDeserializer(), | 41 static_cast<SyncMessage*>(message)->GetReplyDeserializer(), |
| 56 &done_event); | 42 &done_event); |
| 57 | 43 |
| 58 { | 44 { |
| 59 base::AutoLock auto_lock(lock_); | 45 base::AutoLock auto_lock(lock_); |
| 60 // Can't use this class on the main thread or else it can lead to deadlocks. | 46 // Can't use this class on the main thread or else it can lead to deadlocks. |
| 61 // Also by definition, can't use this on IO thread since we're blocking it. | 47 // Also by definition, can't use this on IO thread since we're blocking it. |
| 62 if (base::ThreadTaskRunnerHandle::IsSet()) { | 48 if (base::ThreadTaskRunnerHandle::IsSet()) { |
| 63 DCHECK(base::ThreadTaskRunnerHandle::Get() != listener_task_runner_); | 49 DCHECK(base::ThreadTaskRunnerHandle::Get() != listener_task_runner_); |
| 64 DCHECK(base::ThreadTaskRunnerHandle::Get() != io_task_runner_); | 50 DCHECK(base::ThreadTaskRunnerHandle::Get() != io_task_runner_); |
| 65 } | 51 } |
| 66 pending_sync_messages_.insert(&pending_message); | 52 pending_sync_messages_.insert(&pending_message); |
| 67 | 53 |
| 68 if (io_task_runner_.get()) { | 54 if (io_task_runner_.get()) { |
| 69 io_task_runner_->PostTask( | 55 io_task_runner_->PostTask( |
| 70 FROM_HERE, | 56 FROM_HERE, |
| 71 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); | 57 base::Bind(&SyncMessageFilter::SendOnIOThread, this, message)); |
| 72 } else { | 58 } else { |
| 73 pending_messages_.emplace_back(base::WrapUnique(message)); | 59 pending_messages_.push_back(message); |
| 74 } | 60 } |
| 75 } | 61 } |
| 76 | 62 |
| 77 bool done = false; | 63 base::WaitableEvent* events[2] = { shutdown_event_, &done_event }; |
| 78 bool shutdown = false; | 64 if (base::WaitableEvent::WaitMany(events, 2) == 1) { |
| 79 bool error = false; | |
| 80 scoped_refptr<mojo::SyncHandleRegistry> registry = | |
| 81 mojo::SyncHandleRegistry::current(); | |
| 82 registry->RegisterHandle(shutdown_mojo_event_.GetHandle(), | |
| 83 MOJO_HANDLE_SIGNAL_READABLE, | |
| 84 base::Bind(&OnSyncHandleReady, &shutdown, &error)); | |
| 85 registry->RegisterHandle(done_event.GetHandle(), | |
| 86 MOJO_HANDLE_SIGNAL_READABLE, | |
| 87 base::Bind(&OnSyncHandleReady, &done, &error)); | |
| 88 | |
| 89 const bool* stop_flags[] = { &done, &shutdown }; | |
| 90 bool result = registry->WatchAllHandles(stop_flags, 2); | |
| 91 DCHECK(result); | |
| 92 DCHECK(!error); | |
| 93 | |
| 94 if (done) { | |
| 95 TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), | 65 TRACE_EVENT_FLOW_END0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), |
| 96 "SyncMessageFilter::Send", &done_event); | 66 "SyncMessageFilter::Send", &done_event); |
| 97 } | 67 } |
| 98 registry->UnregisterHandle(shutdown_mojo_event_.GetHandle()); | |
| 99 registry->UnregisterHandle(done_event.GetHandle()); | |
| 100 | 68 |
| 101 { | 69 { |
| 102 base::AutoLock auto_lock(lock_); | 70 base::AutoLock auto_lock(lock_); |
| 103 delete pending_message.deserializer; | 71 delete pending_message.deserializer; |
| 104 pending_sync_messages_.erase(&pending_message); | 72 pending_sync_messages_.erase(&pending_message); |
| 105 } | 73 } |
| 106 | 74 |
| 107 return pending_message.send_result; | 75 return pending_message.send_result; |
| 108 } | 76 } |
| 109 | 77 |
| 110 void SyncMessageFilter::OnFilterAdded(Sender* sender) { | 78 void SyncMessageFilter::OnFilterAdded(Sender* sender) { |
| 111 std::vector<std::unique_ptr<Message>> pending_messages; | 79 std::vector<Message*> pending_messages; |
| 112 { | 80 { |
| 113 base::AutoLock auto_lock(lock_); | 81 base::AutoLock auto_lock(lock_); |
| 114 sender_ = sender; | 82 sender_ = sender; |
| 115 io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 83 io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 116 shutdown_watcher_.StartWatching( | 84 pending_messages_.release(&pending_messages); |
| 117 shutdown_event_, | |
| 118 base::Bind(&SyncMessageFilter::OnShutdownEventSignaled, this)); | |
| 119 std::swap(pending_messages_, pending_messages); | |
| 120 } | 85 } |
| 121 for (auto& msg : pending_messages) | 86 for (auto* msg : pending_messages) |
| 122 SendOnIOThread(msg.release()); | 87 SendOnIOThread(msg); |
| 123 } | 88 } |
| 124 | 89 |
| 125 void SyncMessageFilter::OnChannelError() { | 90 void SyncMessageFilter::OnChannelError() { |
| 126 base::AutoLock auto_lock(lock_); | 91 base::AutoLock auto_lock(lock_); |
| 127 sender_ = NULL; | 92 sender_ = NULL; |
| 128 shutdown_watcher_.StopWatching(); | |
| 129 SignalAllEvents(); | 93 SignalAllEvents(); |
| 130 } | 94 } |
| 131 | 95 |
| 132 void SyncMessageFilter::OnChannelClosing() { | 96 void SyncMessageFilter::OnChannelClosing() { |
| 133 base::AutoLock auto_lock(lock_); | 97 base::AutoLock auto_lock(lock_); |
| 134 sender_ = NULL; | 98 sender_ = NULL; |
| 135 shutdown_watcher_.StopWatching(); | |
| 136 SignalAllEvents(); | 99 SignalAllEvents(); |
| 137 } | 100 } |
| 138 | 101 |
| 139 bool SyncMessageFilter::OnMessageReceived(const Message& message) { | 102 bool SyncMessageFilter::OnMessageReceived(const Message& message) { |
| 140 base::AutoLock auto_lock(lock_); | 103 base::AutoLock auto_lock(lock_); |
| 141 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); | 104 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); |
| 142 iter != pending_sync_messages_.end(); ++iter) { | 105 iter != pending_sync_messages_.end(); ++iter) { |
| 143 if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) { | 106 if (SyncMessage::IsMessageReplyTo(message, (*iter)->id)) { |
| 144 if (!message.is_reply_error()) { | 107 if (!message.is_reply_error()) { |
| 145 (*iter)->send_result = | 108 (*iter)->send_result = |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 lock_.AssertAcquired(); | 150 lock_.AssertAcquired(); |
| 188 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); | 151 for (PendingSyncMessages::iterator iter = pending_sync_messages_.begin(); |
| 189 iter != pending_sync_messages_.end(); ++iter) { | 152 iter != pending_sync_messages_.end(); ++iter) { |
| 190 TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), | 153 TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"), |
| 191 "SyncMessageFilter::SignalAllEvents", | 154 "SyncMessageFilter::SignalAllEvents", |
| 192 (*iter)->done_event); | 155 (*iter)->done_event); |
| 193 (*iter)->done_event->Signal(); | 156 (*iter)->done_event->Signal(); |
| 194 } | 157 } |
| 195 } | 158 } |
| 196 | 159 |
| 197 void SyncMessageFilter::OnShutdownEventSignaled(base::WaitableEvent* event) { | |
| 198 DCHECK_EQ(event, shutdown_event_); | |
| 199 shutdown_mojo_event_.Signal(); | |
| 200 } | |
| 201 | |
| 202 } // namespace IPC | 160 } // namespace IPC |
| OLD | NEW |