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

Side by Side Diff: components/arc/arc_bridge_bootstrap.cc

Issue 2133653002: arc: Notify ARC instance failures via callbacks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address hidehiko's comments. Created 4 years, 5 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "components/arc/arc_bridge_bootstrap.h" 5 #include "components/arc/arc_bridge_bootstrap.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <grp.h> 8 #include <grp.h>
9 #include <unistd.h> 9 #include <unistd.h>
10 10
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 // STOPPED 66 // STOPPED
67 // Start() -> 67 // Start() ->
68 // SOCKET_CREATING 68 // SOCKET_CREATING
69 // CreateSocket() -> OnSocketCreated() -> 69 // CreateSocket() -> OnSocketCreated() ->
70 // STARTING 70 // STARTING
71 // StartArcInstance() -> OnInstanceStarted() -> 71 // StartArcInstance() -> OnInstanceStarted() ->
72 // STARTED 72 // STARTED
73 // AcceptInstanceConnection() -> OnInstanceConnected() -> 73 // AcceptInstanceConnection() -> OnInstanceConnected() ->
74 // READY 74 // READY
75 // 75 //
76 // When Stop() is called from any state, either because an operation 76 // When Stop() or AbortBoot() is called from any state, either because an
77 // resulted in an error or because the user is logging out: 77 // operation resulted in an error or because the user is logging out:
78 // 78 //
79 // (any) 79 // (any)
80 // Stop() -> 80 // Stop()/AbortBoot() ->
81 // STOPPING 81 // STOPPING
82 // StopInstance() -> 82 // StopInstance() ->
83 // STOPPED 83 // STOPPED
84 // 84 //
85 // When the instance crashes while it was ready, it will be stopped: 85 // When the instance crashes while it was ready, it will be stopped:
86 // READY -> STOPPING -> STOPPED 86 // READY -> STOPPING -> STOPPED
87 // and then restarted: 87 // and then restarted:
88 // STOPPED -> SOCKET_CREATING -> ... -> READY). 88 // STOPPED -> SOCKET_CREATING -> ... -> READY).
89 //
90 // Note: Order of constants below matters. Please make sure to sort them
91 // in chronological order.
89 enum class State { 92 enum class State {
90 // ARC is not currently running. 93 // ARC is not currently running.
91 STOPPED, 94 STOPPED,
92 95
93 // An UNIX socket is being created. 96 // An UNIX socket is being created.
94 SOCKET_CREATING, 97 SOCKET_CREATING,
95 98
96 // The request to start the instance has been sent. 99 // The request to start the instance has been sent.
97 STARTING, 100 STARTING,
98 101
99 // The instance has started. Waiting for it to connect to the IPC bridge. 102 // The instance has started. Waiting for it to connect to the IPC bridge.
100 STARTED, 103 STARTED,
101 104
102 // The instance is fully connected. 105 // The instance is fully connected.
103 READY, 106 READY,
104 107
105 // The request to shut down the instance has been sent. 108 // The request to shut down the instance has been sent.
106 STOPPING, 109 STOPPING,
107 }; 110 };
108 111
109 ArcBridgeBootstrapImpl(); 112 ArcBridgeBootstrapImpl();
110 ~ArcBridgeBootstrapImpl() override; 113 ~ArcBridgeBootstrapImpl() override;
111 114
112 // ArcBridgeBootstrap: 115 // ArcBridgeBootstrap:
113 void Start() override; 116 void Start() override;
114 void Stop() override; 117 void Stop() override;
115 118
116 private: 119 private:
120 // Aborts ARC instance boot. This is called from various state-machine
121 // functions when they encounter an error during boot.
122 void AbortBoot(ArcBridgeService::StopReason reason);
123
117 // Creates the UNIX socket on the bootstrap thread and then processes its 124 // Creates the UNIX socket on the bootstrap thread and then processes its
118 // file descriptor. 125 // file descriptor.
119 static base::ScopedFD CreateSocket(); 126 static base::ScopedFD CreateSocket();
120 void OnSocketCreated(base::ScopedFD fd); 127 void OnSocketCreated(base::ScopedFD fd);
121 128
122 // Synchronously accepts a connection on |socket_fd| and then processes the 129 // Synchronously accepts a connection on |socket_fd| and then processes the
123 // connected socket's file descriptor. 130 // connected socket's file descriptor.
124 static base::ScopedFD AcceptInstanceConnection(base::ScopedFD socket_fd); 131 static base::ScopedFD AcceptInstanceConnection(base::ScopedFD socket_fd);
125 void OnInstanceConnected(base::ScopedFD fd); 132 void OnInstanceConnected(base::ScopedFD fd);
126 133
127 void SetState(State state); 134 void SetState(State state);
128 135
129 // DBus callbacks. 136 // DBus callbacks.
130 void OnInstanceStarted(base::ScopedFD socket_fd, bool success); 137 void OnInstanceStarted(base::ScopedFD socket_fd, bool success);
131 138
132 // chromeos::SessionManagerClient::Observer: 139 // chromeos::SessionManagerClient::Observer:
133 void ArcInstanceStopped(bool clean) override; 140 void ArcInstanceStopped(bool clean) override;
134 141
135 // The state of the bootstrap connection. 142 // The state of the bootstrap connection.
136 State state_ = State::STOPPED; 143 State state_ = State::STOPPED;
137 144
145 // The reason the ARC instance is stopped.
146 ArcBridgeService::StopReason stop_reason_ =
147 ArcBridgeService::StopReason::SHUTDOWN;
148
138 base::ThreadChecker thread_checker_; 149 base::ThreadChecker thread_checker_;
139 150
140 // WeakPtrFactory to use callbacks. 151 // WeakPtrFactory to use callbacks.
141 base::WeakPtrFactory<ArcBridgeBootstrapImpl> weak_factory_; 152 base::WeakPtrFactory<ArcBridgeBootstrapImpl> weak_factory_;
142 153
143 private: 154 private:
144 DISALLOW_COPY_AND_ASSIGN(ArcBridgeBootstrapImpl); 155 DISALLOW_COPY_AND_ASSIGN(ArcBridgeBootstrapImpl);
145 }; 156 };
146 157
147 ArcBridgeBootstrapImpl::ArcBridgeBootstrapImpl() 158 ArcBridgeBootstrapImpl::ArcBridgeBootstrapImpl()
(...skipping 13 matching lines...) Expand all
161 client->RemoveObserver(this); 172 client->RemoveObserver(this);
162 } 173 }
163 174
164 void ArcBridgeBootstrapImpl::Start() { 175 void ArcBridgeBootstrapImpl::Start() {
165 DCHECK(thread_checker_.CalledOnValidThread()); 176 DCHECK(thread_checker_.CalledOnValidThread());
166 DCHECK(delegate_); 177 DCHECK(delegate_);
167 if (state_ != State::STOPPED) { 178 if (state_ != State::STOPPED) {
168 VLOG(1) << "Start() called when instance is not stopped"; 179 VLOG(1) << "Start() called when instance is not stopped";
169 return; 180 return;
170 } 181 }
182 stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN;
171 SetState(State::SOCKET_CREATING); 183 SetState(State::SOCKET_CREATING);
172 base::PostTaskAndReplyWithResult( 184 base::PostTaskAndReplyWithResult(
173 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 185 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
174 base::Bind(&ArcBridgeBootstrapImpl::CreateSocket), 186 base::Bind(&ArcBridgeBootstrapImpl::CreateSocket),
175 base::Bind(&ArcBridgeBootstrapImpl::OnSocketCreated, 187 base::Bind(&ArcBridgeBootstrapImpl::OnSocketCreated,
176 weak_factory_.GetWeakPtr())); 188 weak_factory_.GetWeakPtr()));
177 } 189 }
178 190
179 // static 191 // static
180 base::ScopedFD ArcBridgeBootstrapImpl::CreateSocket() { 192 base::ScopedFD ArcBridgeBootstrapImpl::CreateSocket() {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 void ArcBridgeBootstrapImpl::OnSocketCreated(base::ScopedFD socket_fd) { 241 void ArcBridgeBootstrapImpl::OnSocketCreated(base::ScopedFD socket_fd) {
230 DCHECK(thread_checker_.CalledOnValidThread()); 242 DCHECK(thread_checker_.CalledOnValidThread());
231 if (state_ != State::SOCKET_CREATING) { 243 if (state_ != State::SOCKET_CREATING) {
232 VLOG(1) << "Stop() called while connecting"; 244 VLOG(1) << "Stop() called while connecting";
233 return; 245 return;
234 } 246 }
235 SetState(State::STARTING); 247 SetState(State::STARTING);
236 248
237 if (!socket_fd.is_valid()) { 249 if (!socket_fd.is_valid()) {
238 LOG(ERROR) << "ARC: Error creating socket"; 250 LOG(ERROR) << "ARC: Error creating socket";
239 Stop(); 251 AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
240 return; 252 return;
241 } 253 }
242 254
243 user_manager::UserManager* user_manager = user_manager::UserManager::Get(); 255 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
244 DCHECK(user_manager->GetPrimaryUser()); 256 DCHECK(user_manager->GetPrimaryUser());
245 const cryptohome::Identification cryptohome_id( 257 const cryptohome::Identification cryptohome_id(
246 user_manager->GetPrimaryUser()->GetAccountId()); 258 user_manager->GetPrimaryUser()->GetAccountId());
247 259
248 chromeos::SessionManagerClient* session_manager_client = 260 chromeos::SessionManagerClient* session_manager_client =
249 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); 261 chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
250 session_manager_client->StartArcInstance( 262 session_manager_client->StartArcInstance(
251 cryptohome_id, 263 cryptohome_id,
252 base::Bind(&ArcBridgeBootstrapImpl::OnInstanceStarted, 264 base::Bind(&ArcBridgeBootstrapImpl::OnInstanceStarted,
253 weak_factory_.GetWeakPtr(), base::Passed(&socket_fd))); 265 weak_factory_.GetWeakPtr(), base::Passed(&socket_fd)));
254 } 266 }
255 267
256 void ArcBridgeBootstrapImpl::OnInstanceStarted(base::ScopedFD socket_fd, 268 void ArcBridgeBootstrapImpl::OnInstanceStarted(base::ScopedFD socket_fd,
257 bool success) { 269 bool success) {
258 DCHECK(thread_checker_.CalledOnValidThread()); 270 DCHECK(thread_checker_.CalledOnValidThread());
259 if (!success) { 271 if (!success) {
260 LOG(ERROR) << "Failed to start ARC instance"; 272 LOG(ERROR) << "Failed to start ARC instance";
261 // Roll back the state to SOCKET_CREATING to avoid sending the D-Bus signal 273 // Roll back the state to SOCKET_CREATING to avoid sending the D-Bus signal
262 // to stop the failed instance. 274 // to stop the failed instance.
263 SetState(State::SOCKET_CREATING); 275 SetState(State::SOCKET_CREATING);
264 Stop(); 276 AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
265 return; 277 return;
266 } 278 }
267 if (state_ != State::STARTING) { 279 if (state_ != State::STARTING) {
268 VLOG(1) << "Stop() called when ARC is not running"; 280 VLOG(1) << "Stop() called when ARC is not running";
269 return; 281 return;
270 } 282 }
271 SetState(State::STARTED); 283 SetState(State::STARTED);
272 284
273 base::PostTaskAndReplyWithResult( 285 base::PostTaskAndReplyWithResult(
274 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 286 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 } 323 }
312 324
313 void ArcBridgeBootstrapImpl::OnInstanceConnected(base::ScopedFD fd) { 325 void ArcBridgeBootstrapImpl::OnInstanceConnected(base::ScopedFD fd) {
314 DCHECK(thread_checker_.CalledOnValidThread()); 326 DCHECK(thread_checker_.CalledOnValidThread());
315 if (state_ != State::STARTED) { 327 if (state_ != State::STARTED) {
316 VLOG(1) << "Stop() called when ARC is not running"; 328 VLOG(1) << "Stop() called when ARC is not running";
317 return; 329 return;
318 } 330 }
319 if (!fd.is_valid()) { 331 if (!fd.is_valid()) {
320 LOG(ERROR) << "Invalid handle"; 332 LOG(ERROR) << "Invalid handle";
333 AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
321 return; 334 return;
322 } 335 }
323 mojo::ScopedMessagePipeHandle server_pipe = mojo::edk::CreateMessagePipe( 336 mojo::ScopedMessagePipeHandle server_pipe = mojo::edk::CreateMessagePipe(
324 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release()))); 337 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release())));
325 if (!server_pipe.is_valid()) { 338 if (!server_pipe.is_valid()) {
326 LOG(ERROR) << "Invalid pipe"; 339 LOG(ERROR) << "Invalid pipe";
340 AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
327 return; 341 return;
328 } 342 }
329 SetState(State::READY); 343 SetState(State::READY);
330 mojom::ArcBridgeInstancePtr instance; 344 mojom::ArcBridgeInstancePtr instance;
331 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>( 345 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>(
332 std::move(server_pipe), 0u)); 346 std::move(server_pipe), 0u));
333 delegate_->OnConnectionEstablished(std::move(instance)); 347 delegate_->OnConnectionEstablished(std::move(instance));
334 } 348 }
335 349
336 void ArcBridgeBootstrapImpl::Stop() { 350 void ArcBridgeBootstrapImpl::Stop() {
337 DCHECK(thread_checker_.CalledOnValidThread()); 351 DCHECK(thread_checker_.CalledOnValidThread());
338 if (state_ == State::STOPPED || state_ == State::STOPPING) { 352 if (state_ == State::STOPPED || state_ == State::STOPPING) {
339 VLOG(1) << "Stop() called when ARC is not running"; 353 VLOG(1) << "Stop() called when ARC is not running";
340 return; 354 return;
341 } 355 }
342 if (state_ == State::SOCKET_CREATING) { 356 if (state_ < State::STARTING) {
343 // This was stopped before the D-Bus command to start the instance. Skip 357 // This was stopped before the D-Bus command to start the instance. Skip
344 // the D-Bus command to stop it. 358 // the D-Bus command to stop it.
345 SetState(State::STOPPING); 359 SetState(State::STOPPED);
346 ArcInstanceStopped(true);
347 return; 360 return;
348 } 361 }
349 SetState(State::STOPPING); 362 SetState(State::STOPPING);
350 // Notification will arrive through ArcInstanceStopped(). 363 // Notification will arrive through ArcInstanceStopped().
351 chromeos::SessionManagerClient* session_manager_client = 364 chromeos::SessionManagerClient* session_manager_client =
352 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); 365 chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
353 session_manager_client->StopArcInstance( 366 session_manager_client->StopArcInstance(
354 base::Bind(&DoNothingInstanceStopped)); 367 base::Bind(&DoNothingInstanceStopped));
355 } 368 }
356 369
370 void ArcBridgeBootstrapImpl::AbortBoot(ArcBridgeService::StopReason reason) {
371 DCHECK(thread_checker_.CalledOnValidThread());
372 DCHECK(reason != ArcBridgeService::StopReason::SHUTDOWN);
373 // In case of multiple errors, report the first one.
374 if (stop_reason_ == ArcBridgeService::StopReason::SHUTDOWN) {
375 stop_reason_ = reason;
376 }
377 Stop();
378 }
379
357 void ArcBridgeBootstrapImpl::ArcInstanceStopped(bool clean) { 380 void ArcBridgeBootstrapImpl::ArcInstanceStopped(bool clean) {
358 DCHECK(thread_checker_.CalledOnValidThread()); 381 DCHECK(thread_checker_.CalledOnValidThread());
359 if (!clean) 382 if (!clean) {
360 LOG(ERROR) << "ARC instance crashed"; 383 LOG(ERROR) << "ARC instance crashed";
361 DCHECK(delegate_); 384 // In case of multiple errors, report the first one.
385 if (stop_reason_ == ArcBridgeService::StopReason::SHUTDOWN) {
386 stop_reason_ = ArcBridgeService::StopReason::CRASH;
387 }
388 }
362 SetState(State::STOPPED); 389 SetState(State::STOPPED);
363 delegate_->OnStopped();
364 } 390 }
365 391
366 void ArcBridgeBootstrapImpl::SetState(State state) { 392 void ArcBridgeBootstrapImpl::SetState(State state) {
367 DCHECK(thread_checker_.CalledOnValidThread()); 393 DCHECK(thread_checker_.CalledOnValidThread());
368 // DCHECK on enum classes not supported. 394 // DCHECK on enum classes not supported.
369 DCHECK(state_ != state); 395 DCHECK(state_ != state);
370 state_ = state; 396 state_ = state;
371 VLOG(2) << "State: " << static_cast<uint32_t>(state_); 397 VLOG(2) << "State: " << static_cast<uint32_t>(state_);
398 if (state_ == State::STOPPED) {
399 DCHECK(delegate_);
400 delegate_->OnStopped(stop_reason_);
401 }
372 } 402 }
373 403
374 } // namespace 404 } // namespace
375 405
376 // static 406 // static
377 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() { 407 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() {
378 return base::WrapUnique(new ArcBridgeBootstrapImpl()); 408 return base::WrapUnique(new ArcBridgeBootstrapImpl());
379 } 409 }
380 410
381 } // namespace arc 411 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698