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

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: . 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(AbortReason 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
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 void ArcBridgeBootstrapImpl::OnSocketCreated(base::ScopedFD socket_fd) { 236 void ArcBridgeBootstrapImpl::OnSocketCreated(base::ScopedFD socket_fd) {
230 DCHECK(thread_checker_.CalledOnValidThread()); 237 DCHECK(thread_checker_.CalledOnValidThread());
231 if (state_ != State::SOCKET_CREATING) { 238 if (state_ != State::SOCKET_CREATING) {
232 VLOG(1) << "Stop() called while connecting"; 239 VLOG(1) << "Stop() called while connecting";
233 return; 240 return;
234 } 241 }
235 SetState(State::STARTING); 242 SetState(State::STARTING);
236 243
237 if (!socket_fd.is_valid()) { 244 if (!socket_fd.is_valid()) {
238 LOG(ERROR) << "ARC: Error creating socket"; 245 LOG(ERROR) << "ARC: Error creating socket";
239 Stop(); 246 AbortBoot(AbortReason::GENERIC_BOOT_FAILURE);
240 return; 247 return;
241 } 248 }
242 249
243 user_manager::UserManager* user_manager = user_manager::UserManager::Get(); 250 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
244 DCHECK(user_manager->GetPrimaryUser()); 251 DCHECK(user_manager->GetPrimaryUser());
245 const cryptohome::Identification cryptohome_id( 252 const cryptohome::Identification cryptohome_id(
246 user_manager->GetPrimaryUser()->GetAccountId()); 253 user_manager->GetPrimaryUser()->GetAccountId());
247 254
248 chromeos::SessionManagerClient* session_manager_client = 255 chromeos::SessionManagerClient* session_manager_client =
249 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); 256 chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
250 session_manager_client->StartArcInstance( 257 session_manager_client->StartArcInstance(
251 cryptohome_id, 258 cryptohome_id,
252 base::Bind(&ArcBridgeBootstrapImpl::OnInstanceStarted, 259 base::Bind(&ArcBridgeBootstrapImpl::OnInstanceStarted,
253 weak_factory_.GetWeakPtr(), base::Passed(&socket_fd))); 260 weak_factory_.GetWeakPtr(), base::Passed(&socket_fd)));
254 } 261 }
255 262
256 void ArcBridgeBootstrapImpl::OnInstanceStarted(base::ScopedFD socket_fd, 263 void ArcBridgeBootstrapImpl::OnInstanceStarted(base::ScopedFD socket_fd,
257 bool success) { 264 bool success) {
258 DCHECK(thread_checker_.CalledOnValidThread()); 265 DCHECK(thread_checker_.CalledOnValidThread());
259 if (!success) { 266 if (!success) {
260 LOG(ERROR) << "Failed to start ARC instance"; 267 LOG(ERROR) << "Failed to start ARC instance";
261 // Roll back the state to SOCKET_CREATING to avoid sending the D-Bus signal 268 // Roll back the state to SOCKET_CREATING to avoid sending the D-Bus signal
262 // to stop the failed instance. 269 // to stop the failed instance.
263 SetState(State::SOCKET_CREATING); 270 SetState(State::SOCKET_CREATING);
264 Stop(); 271 AbortBoot(AbortReason::GENERIC_BOOT_FAILURE);
265 return; 272 return;
266 } 273 }
267 if (state_ != State::STARTING) { 274 if (state_ != State::STARTING) {
268 VLOG(1) << "Stop() called when ARC is not running"; 275 VLOG(1) << "Stop() called when ARC is not running";
269 return; 276 return;
270 } 277 }
271 SetState(State::STARTED); 278 SetState(State::STARTED);
272 279
273 base::PostTaskAndReplyWithResult( 280 base::PostTaskAndReplyWithResult(
274 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 281 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 } 318 }
312 319
313 void ArcBridgeBootstrapImpl::OnInstanceConnected(base::ScopedFD fd) { 320 void ArcBridgeBootstrapImpl::OnInstanceConnected(base::ScopedFD fd) {
314 DCHECK(thread_checker_.CalledOnValidThread()); 321 DCHECK(thread_checker_.CalledOnValidThread());
315 if (state_ != State::STARTED) { 322 if (state_ != State::STARTED) {
316 VLOG(1) << "Stop() called when ARC is not running"; 323 VLOG(1) << "Stop() called when ARC is not running";
317 return; 324 return;
318 } 325 }
319 if (!fd.is_valid()) { 326 if (!fd.is_valid()) {
320 LOG(ERROR) << "Invalid handle"; 327 LOG(ERROR) << "Invalid handle";
328 AbortBoot(AbortReason::GENERIC_BOOT_FAILURE);
321 return; 329 return;
322 } 330 }
323 mojo::ScopedMessagePipeHandle server_pipe = mojo::edk::CreateMessagePipe( 331 mojo::ScopedMessagePipeHandle server_pipe = mojo::edk::CreateMessagePipe(
324 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release()))); 332 mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release())));
325 if (!server_pipe.is_valid()) { 333 if (!server_pipe.is_valid()) {
326 LOG(ERROR) << "Invalid pipe"; 334 LOG(ERROR) << "Invalid pipe";
335 AbortBoot(AbortReason::GENERIC_BOOT_FAILURE);
327 return; 336 return;
328 } 337 }
329 SetState(State::READY); 338 SetState(State::READY);
330 mojom::ArcBridgeInstancePtr instance; 339 mojom::ArcBridgeInstancePtr instance;
331 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>( 340 instance.Bind(mojo::InterfacePtrInfo<mojom::ArcBridgeInstance>(
332 std::move(server_pipe), 0u)); 341 std::move(server_pipe), 0u));
333 delegate_->OnConnectionEstablished(std::move(instance)); 342 delegate_->OnConnectionEstablished(std::move(instance));
334 } 343 }
335 344
336 void ArcBridgeBootstrapImpl::Stop() { 345 void ArcBridgeBootstrapImpl::Stop() {
337 DCHECK(thread_checker_.CalledOnValidThread()); 346 DCHECK(thread_checker_.CalledOnValidThread());
338 if (state_ == State::STOPPED || state_ == State::STOPPING) { 347 if (state_ == State::STOPPED || state_ == State::STOPPING) {
339 VLOG(1) << "Stop() called when ARC is not running"; 348 VLOG(1) << "Stop() called when ARC is not running";
340 return; 349 return;
341 } 350 }
342 if (state_ == State::SOCKET_CREATING) { 351 if (state_ < State::STARTING) {
343 // This was stopped before the D-Bus command to start the instance. Skip 352 // This was stopped before the D-Bus command to start the instance. Skip
344 // the D-Bus command to stop it. 353 // the D-Bus command to stop it.
345 SetState(State::STOPPING); 354 SetState(State::STOPPED);
346 ArcInstanceStopped(true);
347 return; 355 return;
348 } 356 }
349 SetState(State::STOPPING); 357 SetState(State::STOPPING);
350 // Notification will arrive through ArcInstanceStopped(). 358 // Notification will arrive through ArcInstanceStopped().
351 chromeos::SessionManagerClient* session_manager_client = 359 chromeos::SessionManagerClient* session_manager_client =
352 chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); 360 chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
353 session_manager_client->StopArcInstance( 361 session_manager_client->StopArcInstance(
354 base::Bind(&DoNothingInstanceStopped)); 362 base::Bind(&DoNothingInstanceStopped));
355 } 363 }
356 364
365 void ArcBridgeBootstrapImpl::AbortBoot(AbortReason reason) {
366 DCHECK(thread_checker_.CalledOnValidThread());
367 DCHECK(delegate_);
368 delegate_->OnAborting(reason);
369 Stop();
370 }
371
357 void ArcBridgeBootstrapImpl::ArcInstanceStopped(bool clean) { 372 void ArcBridgeBootstrapImpl::ArcInstanceStopped(bool clean) {
358 DCHECK(thread_checker_.CalledOnValidThread()); 373 DCHECK(thread_checker_.CalledOnValidThread());
359 if (!clean) 374 if (!clean) {
360 LOG(ERROR) << "ARC instance crashed"; 375 LOG(ERROR) << "ARC instance crashed";
361 DCHECK(delegate_); 376 DCHECK(delegate_);
377 delegate_->OnAborting(AbortReason::CRASH);
378 }
362 SetState(State::STOPPED); 379 SetState(State::STOPPED);
363 delegate_->OnStopped();
364 } 380 }
365 381
366 void ArcBridgeBootstrapImpl::SetState(State state) { 382 void ArcBridgeBootstrapImpl::SetState(State state) {
367 DCHECK(thread_checker_.CalledOnValidThread()); 383 DCHECK(thread_checker_.CalledOnValidThread());
368 // DCHECK on enum classes not supported. 384 // DCHECK on enum classes not supported.
369 DCHECK(state_ != state); 385 DCHECK(state_ != state);
370 state_ = state; 386 state_ = state;
371 VLOG(2) << "State: " << static_cast<uint32_t>(state_); 387 VLOG(2) << "State: " << static_cast<uint32_t>(state_);
388 if (state_ == State::STOPPED) {
389 DCHECK(delegate_);
390 delegate_->OnStopped();
391 }
372 } 392 }
373 393
374 } // namespace 394 } // namespace
375 395
376 // static 396 // static
377 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() { 397 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() {
378 return base::WrapUnique(new ArcBridgeBootstrapImpl()); 398 return base::WrapUnique(new ArcBridgeBootstrapImpl());
379 } 399 }
380 400
381 } // namespace arc 401 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698