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

Side by Side Diff: content/common/mojo/mojo_shell_connection_impl.cc

Issue 2245333005: Fix data races in MojoShellConnectionImpl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/renderer_host/render_process_host_impl.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "content/common/mojo/mojo_shell_connection_impl.h" 5 #include "content/common/mojo/mojo_shell_connection_impl.h"
6 6
7 #include <queue> 7 #include <queue>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 83
84 bool posted = io_task_runner_->PostTask( 84 bool posted = io_task_runner_->PostTask(
85 FROM_HERE, base::Bind(&IOThreadContext::ShutDownOnIOThread, this)); 85 FROM_HERE, base::Bind(&IOThreadContext::ShutDownOnIOThread, this));
86 DCHECK(posted); 86 DCHECK(posted);
87 } 87 }
88 88
89 // Safe to call any time before a message is received from a process. 89 // Safe to call any time before a message is received from a process.
90 // i.e. can be called when starting the process but not afterwards. 90 // i.e. can be called when starting the process but not afterwards.
91 int AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) { 91 int AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) {
92 base::AutoLock lock(lock_); 92 base::AutoLock lock(lock_);
93
93 int id = ++next_filter_id_; 94 int id = ++next_filter_id_;
95
96 // We should never hit this in practice, but let's crash just in case.
97 CHECK_NE(id, kInvalidConnectionFilterId);
98
94 connection_filters_[id] = std::move(filter); 99 connection_filters_[id] = std::move(filter);
95 return id; 100 return id;
96 } 101 }
97 102
98 void RemoveConnectionFilter(int filter_id) { 103 void RemoveConnectionFilter(int filter_id) {
99 io_task_runner_->PostTask( 104 io_task_runner_->PostTask(
100 FROM_HERE, 105 FROM_HERE,
101 base::Bind(&IOThreadContext::RemoveConnectionFilterOnIOThread, this, 106 base::Bind(&IOThreadContext::RemoveConnectionFilterOnIOThread, this,
102 filter_id)); 107 filter_id));
103 } 108 }
104 109
105 // Safe to call any time before Start() is called. 110 // Safe to call any time before Start() is called.
106 void SetDefaultBinderForBrowserConnection( 111 void SetDefaultBinderForBrowserConnection(
107 const shell::InterfaceRegistry::Binder& binder) { 112 const shell::InterfaceRegistry::Binder& binder) {
108 DCHECK(!started_); 113 DCHECK(!started_);
109 default_browser_binder_ = base::Bind( 114 default_browser_binder_ = base::Bind(
110 &IOThreadContext::CallBinderOnTaskRunner, 115 &IOThreadContext::CallBinderOnTaskRunner,
111 base::ThreadTaskRunnerHandle::Get(), binder); 116 base::ThreadTaskRunnerHandle::Get(), binder);
112 } 117 }
113 118
114 private: 119 private:
115 friend class base::RefCountedThreadSafe<IOThreadContext>; 120 friend class base::RefCountedThreadSafe<IOThreadContext>;
116 121
117 class Obs : public base::MessageLoop::DestructionObserver { 122 class MessageLoopObserver : public base::MessageLoop::DestructionObserver {
118 public: 123 public:
119 explicit Obs(base::WeakPtr<IOThreadContext> context) : context_(context) { 124 explicit MessageLoopObserver(base::WeakPtr<IOThreadContext> context)
125 : context_(context) {
120 base::MessageLoop::current()->AddDestructionObserver(this); 126 base::MessageLoop::current()->AddDestructionObserver(this);
121 } 127 }
122 ~Obs() override { 128
129 ~MessageLoopObserver() override {
123 base::MessageLoop::current()->RemoveDestructionObserver(this); 130 base::MessageLoop::current()->RemoveDestructionObserver(this);
124 } 131 }
125 132
133 void ShutDown() {
134 if (!is_active_)
135 return;
136
137 // The call into |context_| below may reenter ShutDown(), hence we set
138 // |is_active_| to false here.
139 is_active_ = false;
140 if (context_)
141 context_->ShutDownOnIOThread();
142
143 delete this;
144 }
145
126 private: 146 private:
127 void WillDestroyCurrentMessageLoop() override { 147 void WillDestroyCurrentMessageLoop() override {
128 if (context_) 148 DCHECK(is_active_);
129 context_->ShutDownOnIOThread(); 149 ShutDown();
130 delete this;
131 } 150 }
132 151
152 bool is_active_ = true;
133 base::WeakPtr<IOThreadContext> context_; 153 base::WeakPtr<IOThreadContext> context_;
134 154
135 DISALLOW_COPY_AND_ASSIGN(Obs); 155 DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver);
136 }; 156 };
137 157
138 ~IOThreadContext() override {} 158 ~IOThreadContext() override {}
139 159
140 void StartOnIOThread() { 160 void StartOnIOThread() {
141 // Should bind |io_thread_checker_| to the context's thread. 161 // Should bind |io_thread_checker_| to the context's thread.
142 DCHECK(io_thread_checker_.CalledOnValidThread()); 162 DCHECK(io_thread_checker_.CalledOnValidThread());
143 service_context_.reset(new shell::ServiceContext( 163 service_context_.reset(new shell::ServiceContext(
144 this, std::move(pending_service_request_), 164 this, std::move(pending_service_request_),
145 std::move(io_thread_connector_), 165 std::move(io_thread_connector_),
146 std::move(pending_connector_request_))); 166 std::move(pending_connector_request_)));
147 new Obs(weak_factory_.GetWeakPtr()); 167
168 // MessageLoopObserver owns itself.
169 message_loop_observer_ =
170 new MessageLoopObserver(weak_factory_.GetWeakPtr());
148 } 171 }
149 172
150 void ShutDownOnIOThread() { 173 void ShutDownOnIOThread() {
151 DCHECK(io_thread_checker_.CalledOnValidThread()); 174 DCHECK(io_thread_checker_.CalledOnValidThread());
175
152 weak_factory_.InvalidateWeakPtrs(); 176 weak_factory_.InvalidateWeakPtrs();
177
178 // Note that this method may be invoked by MessageLoopObserver observing
179 // MessageLoop destruction. In that case, this call to ShutDown is
180 // effectively a no-op. In any case it's safe.
181 message_loop_observer_->ShutDown();
182 message_loop_observer_ = nullptr;
183
184 // Resetting the ServiceContext below may otherwise release the last
185 // reference to this IOThreadContext. We keep it alive until the stack
186 // unwinds.
187 scoped_refptr<IOThreadContext> keepalive(this);
188
153 factory_bindings_.CloseAllBindings(); 189 factory_bindings_.CloseAllBindings();
190 service_context_.reset();
191
192 base::AutoLock lock(lock_);
154 connection_filters_.clear(); 193 connection_filters_.clear();
155 service_context_.reset();
156 } 194 }
157 195
158 void RemoveConnectionFilterOnIOThread(int filter_id) { 196 void RemoveConnectionFilterOnIOThread(int filter_id) {
197 base::AutoLock lock(lock_);
159 auto it = connection_filters_.find(filter_id); 198 auto it = connection_filters_.find(filter_id);
160 DCHECK(it != connection_filters_.end()); 199 DCHECK(it != connection_filters_.end());
161 connection_filters_.erase(it); 200 connection_filters_.erase(it);
162 } 201 }
163 202
164 void OnBrowserConnectionLost() { 203 void OnBrowserConnectionLost() {
165 DCHECK(io_thread_checker_.CalledOnValidThread()); 204 DCHECK(io_thread_checker_.CalledOnValidThread());
166 has_browser_connection_ = false; 205 has_browser_connection_ = false;
167 } 206 }
168 207
(...skipping 13 matching lines...) Expand all
182 shell::InterfaceRegistry* registry) override { 221 shell::InterfaceRegistry* registry) override {
183 DCHECK(io_thread_checker_.CalledOnValidThread()); 222 DCHECK(io_thread_checker_.CalledOnValidThread());
184 std::string remote_app = remote_identity.name(); 223 std::string remote_app = remote_identity.name();
185 if (remote_app == "mojo:shell") { 224 if (remote_app == "mojo:shell") {
186 // Only expose the SCF interface to the shell. 225 // Only expose the SCF interface to the shell.
187 registry->AddInterface<shell::mojom::ServiceFactory>(this); 226 registry->AddInterface<shell::mojom::ServiceFactory>(this);
188 return true; 227 return true;
189 } 228 }
190 229
191 bool accept = false; 230 bool accept = false;
192 for (auto& entry : connection_filters_) { 231 {
193 accept |= entry.second->OnConnect(remote_identity, registry, 232 base::AutoLock lock(lock_);
194 service_context_->connector()); 233 for (auto& entry : connection_filters_) {
234 accept |= entry.second->OnConnect(remote_identity, registry,
235 service_context_->connector());
236 }
195 } 237 }
196 238
197 if (remote_identity.name() == "exe:content_browser" && 239 if (remote_identity.name() == "exe:content_browser" &&
198 !has_browser_connection_) { 240 !has_browser_connection_) {
199 has_browser_connection_ = true; 241 has_browser_connection_ = true;
200 registry->set_default_binder(default_browser_binder_); 242 registry->set_default_binder(default_browser_binder_);
201 registry->SetConnectionLostClosure( 243 registry->SetConnectionLostClosure(
202 base::Bind(&IOThreadContext::OnBrowserConnectionLost, this)); 244 base::Bind(&IOThreadContext::OnBrowserConnectionLost, this));
203 return true; 245 return true;
204 } 246 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 314
273 // Default binder callback used for the browser connection's 315 // Default binder callback used for the browser connection's
274 // InterfaceRegistry. 316 // InterfaceRegistry.
275 // 317 //
276 // TODO(rockot): Remove this once all interfaces exposed to the browser are 318 // TODO(rockot): Remove this once all interfaces exposed to the browser are
277 // exposed via a ConnectionFilter. 319 // exposed via a ConnectionFilter.
278 shell::InterfaceRegistry::Binder default_browser_binder_; 320 shell::InterfaceRegistry::Binder default_browser_binder_;
279 321
280 std::unique_ptr<shell::ServiceContext> service_context_; 322 std::unique_ptr<shell::ServiceContext> service_context_;
281 mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; 323 mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_;
282 std::map<int, std::unique_ptr<ConnectionFilter>> connection_filters_;
283 int next_filter_id_ = kInvalidConnectionFilterId; 324 int next_filter_id_ = kInvalidConnectionFilterId;
284 325
326 // Not owned.
327 MessageLoopObserver* message_loop_observer_ = nullptr;
328
329 // Guards |connection_filters_|.
285 base::Lock lock_; 330 base::Lock lock_;
331 std::map<int, std::unique_ptr<ConnectionFilter>> connection_filters_;
286 332
287 base::WeakPtrFactory<IOThreadContext> weak_factory_; 333 base::WeakPtrFactory<IOThreadContext> weak_factory_;
288 334
289 DISALLOW_COPY_AND_ASSIGN(IOThreadContext); 335 DISALLOW_COPY_AND_ASSIGN(IOThreadContext);
290 }; 336 };
291 337
292 //////////////////////////////////////////////////////////////////////////////// 338 ////////////////////////////////////////////////////////////////////////////////
293 // MojoShellConnection, public: 339 // MojoShellConnection, public:
294 340
295 // static 341 // static
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 488
443 void MojoShellConnectionImpl::GetInterface( 489 void MojoShellConnectionImpl::GetInterface(
444 shell::mojom::InterfaceProvider* provider, 490 shell::mojom::InterfaceProvider* provider,
445 const std::string& interface_name, 491 const std::string& interface_name,
446 mojo::ScopedMessagePipeHandle request_handle) { 492 mojo::ScopedMessagePipeHandle request_handle) {
447 provider->GetInterface(interface_name, std::move(request_handle)); 493 provider->GetInterface(interface_name, std::move(request_handle));
448 } 494 }
449 495
450 } // namespace content 496 } // namespace content
451 497
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_process_host_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698