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

Side by Side Diff: shell/app_child_process.cc

Issue 973203004: Make the shell work in multiprocess mode some apps. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: better (?) comment Created 5 years, 9 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 | « no previous file | shell/context.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "shell/app_child_process.h" 5 #include "shell/app_child_process.h"
6 6
7 #include <unistd.h>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
9 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
10 #include "base/location.h" 12 #include "base/location.h"
11 #include "base/logging.h" 13 #include "base/logging.h"
12 #include "base/macros.h" 14 #include "base/macros.h"
13 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
16 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
17 #include "base/synchronization/waitable_event.h" 19 #include "base/synchronization/waitable_event.h"
18 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
19 #include "base/threading/thread_checker.h" 21 #include "base/threading/thread_checker.h"
20 #include "mojo/common/message_pump_mojo.h" 22 #include "mojo/common/message_pump_mojo.h"
21 #include "mojo/edk/embedder/embedder.h" 23 #include "mojo/edk/embedder/embedder.h"
24 #include "mojo/edk/embedder/process_delegate.h"
22 #include "mojo/edk/embedder/simple_platform_support.h" 25 #include "mojo/edk/embedder/simple_platform_support.h"
23 #include "mojo/public/cpp/system/core.h" 26 #include "mojo/public/cpp/system/core.h"
24 #include "shell/app_child_process.mojom.h" 27 #include "shell/app_child_process.mojom.h"
25 #include "shell/dynamic_service_runner.h" 28 #include "shell/dynamic_service_runner.h"
26 29
27 namespace mojo { 30 namespace mojo {
28 namespace shell { 31 namespace shell {
29 32
30 namespace { 33 namespace {
31 34
32 // Blocker --------------------------------------------------------------------- 35 // Blocker ---------------------------------------------------------------------
33 36
34 // Blocks a thread until another thread unblocks it, at which point it unblocks 37 // Blocks a thread until another thread unblocks it, at which point it unblocks
35 // and runs a closure provided by that thread. 38 // and runs a closure provided by that thread.
36 class Blocker { 39 class Blocker {
37 public: 40 public:
38 class Unblocker { 41 class Unblocker {
39 public: 42 public:
43 explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {}
40 ~Unblocker() {} 44 ~Unblocker() {}
41 45
42 void Unblock(base::Closure run_after) { 46 void Unblock(base::Closure run_after) {
43 DCHECK(blocker_); 47 DCHECK(blocker_);
44 DCHECK(blocker_->run_after_.is_null()); 48 DCHECK(blocker_->run_after_.is_null());
45 blocker_->run_after_ = run_after; 49 blocker_->run_after_ = run_after;
46 blocker_->event_.Signal(); 50 blocker_->event_.Signal();
47 blocker_ = NULL; 51 blocker_ = nullptr;
48 } 52 }
49 53
50 private: 54 private:
51 friend class Blocker;
52 Unblocker(Blocker* blocker) : blocker_(blocker) { DCHECK(blocker_); }
53
54 Blocker* blocker_; 55 Blocker* blocker_;
55 56
56 // Copy and assign allowed. 57 // Copy and assign allowed.
57 }; 58 };
58 59
59 Blocker() : event_(true, false) {} 60 Blocker() : event_(true, false) {}
60 ~Blocker() {} 61 ~Blocker() {}
61 62
62 void Block() { 63 void Block() {
63 DCHECK(run_after_.is_null()); 64 DCHECK(run_after_.is_null());
64 event_.Wait(); 65 event_.Wait();
65 run_after_.Run(); 66 run_after_.Run();
66 } 67 }
67 68
68 Unblocker GetUnblocker() { return Unblocker(this); } 69 Unblocker GetUnblocker() { return Unblocker(this); }
69 70
70 private: 71 private:
71 base::WaitableEvent event_; 72 base::WaitableEvent event_;
72 base::Closure run_after_; 73 base::Closure run_after_;
73 74
74 DISALLOW_COPY_AND_ASSIGN(Blocker); 75 DISALLOW_COPY_AND_ASSIGN(Blocker);
75 }; 76 };
76 77
77 // AppContext ------------------------------------------------------------------ 78 // AppContext ------------------------------------------------------------------
78 79
79 class AppChildControllerImpl; 80 class AppChildControllerImpl;
80 81
81 static void DestroyController(scoped_ptr<AppChildControllerImpl> controller) {
82 }
83
84 // Should be created and initialized on the main thread. 82 // Should be created and initialized on the main thread.
85 class AppContext { 83 class AppContext : public embedder::ProcessDelegate {
86 public: 84 public:
87 AppContext() 85 AppContext()
88 : io_thread_("io_thread"), controller_thread_("controller_thread") {} 86 : io_thread_("io_thread"), controller_thread_("controller_thread") {}
89 ~AppContext() {} 87 ~AppContext() {}
90 88
91 void Init() { 89 void Init() {
92 // Initialize Mojo before starting any threads. 90 // Initialize Mojo before starting any threads.
93 embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>( 91 embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>(
94 new mojo::embedder::SimplePlatformSupport())); 92 new mojo::embedder::SimplePlatformSupport()));
95 93
96 // Create and start our I/O thread. 94 // Create and start our I/O thread.
97 base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); 95 base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0);
98 CHECK(io_thread_.StartWithOptions(io_thread_options)); 96 CHECK(io_thread_.StartWithOptions(io_thread_options));
99 io_runner_ = io_thread_.message_loop_proxy().get(); 97 io_runner_ = io_thread_.message_loop_proxy().get();
100 CHECK(io_runner_.get()); 98 CHECK(io_runner_.get());
101 99
102 // Create and start our controller thread. 100 // Create and start our controller thread.
103 base::Thread::Options controller_thread_options; 101 base::Thread::Options controller_thread_options;
104 controller_thread_options.message_loop_type = 102 controller_thread_options.message_loop_type =
105 base::MessageLoop::TYPE_CUSTOM; 103 base::MessageLoop::TYPE_CUSTOM;
106 controller_thread_options.message_pump_factory = 104 controller_thread_options.message_pump_factory =
107 base::Bind(&common::MessagePumpMojo::Create); 105 base::Bind(&common::MessagePumpMojo::Create);
108 CHECK(controller_thread_.StartWithOptions(controller_thread_options)); 106 CHECK(controller_thread_.StartWithOptions(controller_thread_options));
109 controller_runner_ = controller_thread_.message_loop_proxy().get(); 107 controller_runner_ = controller_thread_.message_loop_proxy().get();
110 CHECK(controller_runner_.get()); 108 CHECK(controller_runner_.get());
109
110 // TODO(vtl): This should be SLAVE, not NONE.
111 embedder::InitIPCSupport(embedder::ProcessType::NONE, controller_runner_,
112 this, io_runner_,
113 embedder::ScopedPlatformHandle());
111 } 114 }
112 115
113 void Shutdown() { 116 void Shutdown() {
117 Blocker blocker;
118 shutdown_unblocker_ = blocker.GetUnblocker();
114 controller_runner_->PostTask( 119 controller_runner_->PostTask(
115 FROM_HERE, base::Bind(&DestroyController, base::Passed(&controller_))); 120 FROM_HERE, base::Bind(&AppContext::ShutdownOnControllerThread,
121 base::Unretained(this)));
122 blocker.Block();
116 } 123 }
117 124
118 base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); } 125 base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); }
119 126
120 base::SingleThreadTaskRunner* controller_runner() const { 127 base::SingleThreadTaskRunner* controller_runner() const {
121 return controller_runner_.get(); 128 return controller_runner_.get();
122 } 129 }
123 130
124 AppChildControllerImpl* controller() const { return controller_.get(); } 131 AppChildControllerImpl* controller() const { return controller_.get(); }
125 132
126 void set_controller(scoped_ptr<AppChildControllerImpl> controller) { 133 void set_controller(scoped_ptr<AppChildControllerImpl> controller) {
127 controller_ = controller.Pass(); 134 controller_ = controller.Pass();
128 } 135 }
129 136
130 private: 137 private:
131 // Accessed only on the controller thread. 138 void ShutdownOnControllerThread() {
132 // IMPORTANT: This must be BEFORE |controller_thread_|, so that the controller 139 // First, destroy the controller.
133 // thread gets joined (and thus |controller_| reset) before |controller_| is 140 controller_.reset();
134 // destroyed. 141
135 scoped_ptr<AppChildControllerImpl> controller_; 142 // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete().
143 embedder::ShutdownIPCSupport();
144 }
145
146 // ProcessDelegate implementation.
147 void OnShutdownComplete() override {
148 shutdown_unblocker_.Unblock(base::Closure());
149 }
136 150
137 base::Thread io_thread_; 151 base::Thread io_thread_;
138 scoped_refptr<base::SingleThreadTaskRunner> io_runner_; 152 scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
139 153
140 base::Thread controller_thread_; 154 base::Thread controller_thread_;
141 scoped_refptr<base::SingleThreadTaskRunner> controller_runner_; 155 scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
142 156
157 // Accessed only on the controller thread.
158 scoped_ptr<AppChildControllerImpl> controller_;
159
160 // Used to unblock the main thread on shutdown.
161 Blocker::Unblocker shutdown_unblocker_;
162
143 DISALLOW_COPY_AND_ASSIGN(AppContext); 163 DISALLOW_COPY_AND_ASSIGN(AppContext);
144 }; 164 };
145 165
146 // AppChildControllerImpl ------------------------------------------------------ 166 // AppChildControllerImpl ------------------------------------------------------
147 167
148 class AppChildControllerImpl : public AppChildController, public ErrorHandler { 168 class AppChildControllerImpl : public AppChildController, public ErrorHandler {
149 public: 169 public:
150 ~AppChildControllerImpl() override { 170 ~AppChildControllerImpl() override {
151 DCHECK(thread_checker_.CalledOnValidThread()); 171 DCHECK(thread_checker_.CalledOnValidThread());
152 172
(...skipping 24 matching lines...) Expand all
177 197
178 app_context->set_controller(impl.Pass()); 198 app_context->set_controller(impl.Pass());
179 } 199 }
180 200
181 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); } 201 void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); }
182 202
183 // |ErrorHandler| methods: 203 // |ErrorHandler| methods:
184 void OnConnectionError() override { 204 void OnConnectionError() override {
185 // A connection error means the connection to the shell is lost. This is not 205 // A connection error means the connection to the shell is lost. This is not
186 // recoverable. 206 // recoverable.
187 CHECK(false) << "Connection error to the shell."; 207 LOG(ERROR) << "Connection error to the shell.";
208 _exit(1);
188 } 209 }
189 210
190 // |AppChildController| methods: 211 // |AppChildController| methods:
191 void StartApp(const String& app_path, 212 void StartApp(const String& app_path,
192 bool clean_app_path, 213 bool clean_app_path,
193 InterfaceRequest<Application> application_request, 214 InterfaceRequest<Application> application_request,
194 const StartAppCallback& on_app_complete) override { 215 const StartAppCallback& on_app_complete) override {
195 DVLOG(2) << "AppChildControllerImpl::StartApp(" << app_path << ", ...)"; 216 DVLOG(2) << "AppChildControllerImpl::StartApp(" << app_path << ", ...)";
196 DCHECK(thread_checker_.CalledOnValidThread()); 217 DCHECK(thread_checker_.CalledOnValidThread());
197 218
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context), 289 base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context),
269 base::Passed(platform_channel()), blocker.GetUnblocker())); 290 base::Passed(platform_channel()), blocker.GetUnblocker()));
270 // This will block, then run whatever the controller wants. 291 // This will block, then run whatever the controller wants.
271 blocker.Block(); 292 blocker.Block();
272 293
273 app_context.Shutdown(); 294 app_context.Shutdown();
274 } 295 }
275 296
276 } // namespace shell 297 } // namespace shell
277 } // namespace mojo 298 } // namespace mojo
OLDNEW
« no previous file with comments | « no previous file | shell/context.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698