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

Side by Side Diff: services/shell/service_manager.cc

Issue 2341853002: ServiceManager: Simplify Instance lifetime management (Closed)
Patch Set: . Created 4 years, 3 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 | « services/shell/service_manager.h ('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 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 "services/shell/service_manager.h" 5 #include "services/shell/service_manager.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 pid_receiver_binding_(this), 126 pid_receiver_binding_(this),
127 weak_factory_(this) { 127 weak_factory_(this) {
128 if (identity_.name() == kServiceManagerName || 128 if (identity_.name() == kServiceManagerName ||
129 identity_.name() == kCatalogName) { 129 identity_.name() == kCatalogName) {
130 pid_ = base::Process::Current().Pid(); 130 pid_ = base::Process::Current().Pid();
131 } 131 }
132 DCHECK_NE(mojom::kInvalidInstanceID, id_); 132 DCHECK_NE(mojom::kInvalidInstanceID, id_);
133 } 133 }
134 134
135 ~Instance() override { 135 ~Instance() override {
136 if (parent_)
137 parent_->RemoveChild(this);
138 // |children_| will be modified during destruction.
139 std::set<Instance*> children = children_;
140 for (auto* child : children)
141 service_manager_->OnInstanceError(child, InstanceErrorType::DESTROY);
142
143 // Shutdown all bindings before we close the runner. This way the process 136 // Shutdown all bindings before we close the runner. This way the process
144 // should see the pipes closed and exit, as well as waking up any potential 137 // should see the pipes closed and exit, as well as waking up any potential
145 // sync/WaitForIncomingResponse(). 138 // sync/WaitForIncomingResponse().
146 service_.reset(); 139 service_.reset();
147 if (pid_receiver_binding_.is_bound()) 140 if (pid_receiver_binding_.is_bound())
148 pid_receiver_binding_.Close(); 141 pid_receiver_binding_.Close();
149 connectors_.CloseAllBindings(); 142 connectors_.CloseAllBindings();
150 service_manager_bindings_.CloseAllBindings(); 143 service_manager_bindings_.CloseAllBindings();
144
145 // Notify the ServiceManager that this Instance is really going away.
146 service_manager_->OnInstanceStopped(identity_);
147
151 // Release |runner_| so that if we are called back to OnRunnerCompleted() 148 // Release |runner_| so that if we are called back to OnRunnerCompleted()
152 // we know we're in the destructor. 149 // we know we're in the destructor.
153 std::unique_ptr<NativeRunner> runner = std::move(runner_); 150 std::unique_ptr<NativeRunner> runner = std::move(runner_);
154 runner.reset(); 151 runner.reset();
155 } 152 }
156 153
157 Instance* parent() { return parent_; } 154 Instance* parent() { return parent_; }
158 155
159 void AddChild(Instance* child) { 156 void AddChild(std::unique_ptr<Instance> child) {
160 children_.insert(child);
161 child->parent_ = this; 157 child->parent_ = this;
158 children_.insert(std::make_pair(child.get(), std::move(child)));
162 } 159 }
163 160
164 void RemoveChild(Instance* child) { 161 void RemoveChild(Instance* child) {
165 auto it = children_.find(child); 162 auto it = children_.find(child);
166 DCHECK(it != children_.end()); 163 DCHECK(it != children_.end());
164
165 // Deletes |child|.
167 children_.erase(it); 166 children_.erase(it);
168 child->parent_ = nullptr;
169 } 167 }
170 168
171 bool ConnectToService(std::unique_ptr<ConnectParams>* connect_params) { 169 bool ConnectToService(std::unique_ptr<ConnectParams>* connect_params) {
172 if (!service_.is_bound()) 170 if (!service_.is_bound())
173 return false; 171 return false;
174 172
175 std::unique_ptr<ConnectParams> params(std::move(*connect_params)); 173 std::unique_ptr<ConnectParams> params(std::move(*connect_params));
176 if (!params->connect_callback().is_null()) { 174 if (!params->connect_callback().is_null()) {
177 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED, 175 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED,
178 identity_.user_id()); 176 identity_.user_id());
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 393
396 uint32_t GenerateUniqueID() const { 394 uint32_t GenerateUniqueID() const {
397 static uint32_t id = mojom::kInvalidInstanceID; 395 static uint32_t id = mojom::kInvalidInstanceID;
398 ++id; 396 ++id;
399 CHECK_NE(mojom::kInvalidInstanceID, id); 397 CHECK_NE(mojom::kInvalidInstanceID, id);
400 return id; 398 return id;
401 } 399 }
402 400
403 void PIDAvailable(base::ProcessId pid) { 401 void PIDAvailable(base::ProcessId pid) {
404 if (pid == base::kNullProcessId) { 402 if (pid == base::kNullProcessId) {
405 service_manager_->OnInstanceError(this, InstanceErrorType::DESTROY); 403 service_manager_->OnInstanceError(this);
406 return; 404 return;
407 } 405 }
408 pid_ = pid; 406 pid_ = pid;
409 service_manager_->NotifyPIDAvailable(identity_, pid_); 407 service_manager_->NotifyPIDAvailable(identity_, pid_);
410 } 408 }
411 409
412 void OnServiceLost(base::WeakPtr<shell::ServiceManager> service_manager) { 410 void OnServiceLost(base::WeakPtr<shell::ServiceManager> service_manager) {
413 service_.reset(); 411 service_.reset();
414 OnConnectionLost(service_manager); 412 OnConnectionLost(service_manager);
415 } 413 }
416 414
417 void OnConnectionLost(base::WeakPtr<shell::ServiceManager> service_manager) { 415 void OnConnectionLost(base::WeakPtr<shell::ServiceManager> service_manager) {
418 // Any time a Connector is lost or we lose the Service connection, it 416 // Any time a Connector is lost or we lose the Service connection, it
419 // may have been the last pipe using this Instance. If so, clean up. 417 // may have been the last pipe using this Instance. If so, clean up.
420 if (service_manager && !service_) { 418 if (service_manager && !service_) {
421 InstanceErrorType instance_error_type = 419 if (connectors_.empty())
422 connectors_.empty() ? InstanceErrorType::DESTROY 420 service_manager->OnInstanceError(this);
423 : InstanceErrorType::LOST_SERVICE; 421 else
424 service_manager->OnInstanceError(this, instance_error_type); 422 service_manager->OnInstanceUnreachable(this);
425 } 423 }
426 } 424 }
427 425
428 void OnInitializeResponse(mojom::ConnectorRequest connector_request) { 426 void OnInitializeResponse(mojom::ConnectorRequest connector_request) {
429 if (connector_request.is_pending()) { 427 if (connector_request.is_pending()) {
430 connectors_.AddBinding(this, std::move(connector_request)); 428 connectors_.AddBinding(this, std::move(connector_request));
431 connectors_.set_connection_error_handler( 429 connectors_.set_connection_error_handler(
432 base::Bind(&Instance::OnConnectionLost, base::Unretained(this), 430 base::Bind(&Instance::OnConnectionLost, base::Unretained(this),
433 service_manager_->GetWeakPtr())); 431 service_manager_->GetWeakPtr()));
434 } 432 }
435 } 433 }
436 434
437 // Callback when NativeRunner completes. 435 // Callback when NativeRunner completes.
438 void OnRunnerCompleted() { 436 void OnRunnerCompleted() {
439 if (!runner_.get()) 437 if (!runner_.get())
440 return; // We're in the destructor. 438 return; // We're in the destructor.
441 439
442 service_manager_->OnInstanceError(this, InstanceErrorType::DESTROY); 440 service_manager_->OnInstanceError(this);
443 } 441 }
444 442
445 shell::ServiceManager* const service_manager_; 443 shell::ServiceManager* const service_manager_;
446 444
447 // An id that identifies this instance. Distinct from pid, as a single process 445 // An id that identifies this instance. Distinct from pid, as a single process
448 // may vend multiple application instances, and this object may exist before a 446 // may vend multiple application instances, and this object may exist before a
449 // process is launched. 447 // process is launched.
450 const uint32_t id_; 448 const uint32_t id_;
451 const Identity identity_; 449 const Identity identity_;
452 const CapabilitySpec capability_spec_; 450 const CapabilitySpec capability_spec_;
453 const bool allow_any_application_; 451 const bool allow_any_application_;
454 std::unique_ptr<NativeRunner> runner_; 452 std::unique_ptr<NativeRunner> runner_;
455 mojom::ServicePtr service_; 453 mojom::ServicePtr service_;
456 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; 454 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_;
457 mojo::BindingSet<mojom::Connector> connectors_; 455 mojo::BindingSet<mojom::Connector> connectors_;
458 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; 456 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_;
459 base::ProcessId pid_ = base::kNullProcessId; 457 base::ProcessId pid_ = base::kNullProcessId;
460 Instance* parent_ = nullptr; 458 Instance* parent_ = nullptr;
461 std::set<Instance*> children_; 459 InstanceMap children_;
462 base::WeakPtrFactory<Instance> weak_factory_; 460 base::WeakPtrFactory<Instance> weak_factory_;
463 461
464 DISALLOW_COPY_AND_ASSIGN(Instance); 462 DISALLOW_COPY_AND_ASSIGN(Instance);
465 }; 463 };
466 464
467 // static 465 // static
468 ServiceManager::TestAPI::TestAPI(ServiceManager* service_manager) 466 ServiceManager::TestAPI::TestAPI(ServiceManager* service_manager)
469 : service_manager_(service_manager) {} 467 : service_manager_(service_manager) {}
470 ServiceManager::TestAPI::~TestAPI() {} 468 ServiceManager::TestAPI::~TestAPI() {}
471 469
(...skipping 21 matching lines...) Expand all
493 instance->StartWithService(std::move(service)); 491 instance->StartWithService(std::move(service));
494 singletons_.insert(kServiceManagerName); 492 singletons_.insert(kServiceManagerName);
495 service_context_.reset(new ServiceContext(this, std::move(request))); 493 service_context_.reset(new ServiceContext(this, std::move(request)));
496 494
497 if (catalog) 495 if (catalog)
498 InitCatalog(std::move(catalog)); 496 InitCatalog(std::move(catalog));
499 } 497 }
500 498
501 ServiceManager::~ServiceManager() { 499 ServiceManager::~ServiceManager() {
502 TerminateServiceManagerConnections(); 500 TerminateServiceManagerConnections();
503 // Terminate any remaining instances.
504 while (!identity_to_instance_.empty()) {
505 OnInstanceError(identity_to_instance_.begin()->second,
506 InstanceErrorType::DESTROY);
507 }
508 while (!instances_without_service_.empty()) {
509 OnInstanceError(*instances_without_service_.begin(),
510 InstanceErrorType::DESTROY);
511 }
512 identity_to_resolver_.clear();
513 } 501 }
514 502
515 void ServiceManager::SetInstanceQuitCallback( 503 void ServiceManager::SetInstanceQuitCallback(
516 base::Callback<void(const Identity&)> callback) { 504 base::Callback<void(const Identity&)> callback) {
517 instance_quit_callback_ = callback; 505 instance_quit_callback_ = callback;
518 } 506 }
519 507
520 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params) { 508 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params) {
521 Connect(std::move(params), nullptr, nullptr); 509 Connect(std::move(params), nullptr, nullptr);
522 } 510 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 mojom::ResolverPtr resolver_ptr; 569 mojom::ResolverPtr resolver_ptr;
582 ConnectToInterface(this, identity, CreateCatalogIdentity(), &resolver_ptr); 570 ConnectToInterface(this, identity, CreateCatalogIdentity(), &resolver_ptr);
583 mojom::Resolver* resolver = resolver_ptr.get(); 571 mojom::Resolver* resolver = resolver_ptr.get();
584 identity_to_resolver_[identity] = std::move(resolver_ptr); 572 identity_to_resolver_[identity] = std::move(resolver_ptr);
585 return resolver; 573 return resolver;
586 } 574 }
587 575
588 void ServiceManager::TerminateServiceManagerConnections() { 576 void ServiceManager::TerminateServiceManagerConnections() {
589 Instance* instance = GetExistingInstance(CreateServiceManagerIdentity()); 577 Instance* instance = GetExistingInstance(CreateServiceManagerIdentity());
590 if (instance) 578 if (instance)
591 OnInstanceError(instance, InstanceErrorType::DESTROY); 579 OnInstanceError(instance);
592 } 580 }
593 581
594 void ServiceManager::OnInstanceError(Instance* instance, 582 void ServiceManager::OnInstanceError(Instance* instance) {
595 InstanceErrorType error_type) {
596 const Identity identity = instance->identity(); 583 const Identity identity = instance->identity();
584 identity_to_instance_.erase(identity);
597 585
598 const bool in_identity_to_instance = 586 if (instance->parent()) {
599 identity_to_instance_.erase(identity) > 0; 587 // Deletes |instance|.
600 const bool in_instances_without_services = 588 instance->parent()->RemoveChild(instance);
601 instances_without_service_.erase(instance) > 0; 589 } else {
602 DCHECK_NE(in_identity_to_instance, in_instances_without_services); 590 auto it = root_instances_.find(instance);
591 DCHECK(it != root_instances_.end());
603 592
604 if (error_type == InstanceErrorType::LOST_SERVICE) { 593 // Deletes |instance|.
605 // |instance| has lost its service but still has connections to it, we need 594 root_instances_.erase(it);
606 // to keep it around. The instance is removed from |identity_to_instance_|
607 // so that if an attempt is made to connect to the same identity a new
608 // Instance is created.
609 instances_without_service_.insert(instance);
610 return;
611 } 595 }
596 }
612 597
598 void ServiceManager::OnInstanceUnreachable(Instance* instance) {
599 // If an Instance becomes unreachable, new connection requests for this
600 // identity will elicit a new Instance instantiation. The unreachable instance
601 // remains alive.
602 identity_to_instance_.erase(instance->identity());
603 }
604
605 void ServiceManager::OnInstanceStopped(const Identity& identity) {
613 listeners_.ForAllPtrs([identity](mojom::ServiceManagerListener* listener) { 606 listeners_.ForAllPtrs([identity](mojom::ServiceManagerListener* listener) {
614 listener->OnServiceStopped(identity); 607 listener->OnServiceStopped(identity);
615 }); 608 });
616 delete instance;
617 if (!instance_quit_callback_.is_null()) 609 if (!instance_quit_callback_.is_null())
618 instance_quit_callback_.Run(identity); 610 instance_quit_callback_.Run(identity);
619 } 611 }
620 612
621 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params, 613 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params,
622 mojom::ServicePtr service, 614 mojom::ServicePtr service,
623 base::WeakPtr<Instance> source_instance) { 615 base::WeakPtr<Instance> source_instance) {
624 TRACE_EVENT_INSTANT1("mojo_shell", "ServiceManager::Connect", 616 TRACE_EVENT_INSTANT1("mojo_shell", "ServiceManager::Connect",
625 TRACE_EVENT_SCOPE_THREAD, "original_name", 617 TRACE_EVENT_SCOPE_THREAD, "original_name",
626 params->target().name()); 618 params->target().name());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 std::unique_ptr<ConnectParams>* params) { 670 std::unique_ptr<ConnectParams>* params) {
679 Instance* instance = GetExistingInstance((*params)->target()); 671 Instance* instance = GetExistingInstance((*params)->target());
680 return instance && instance->ConnectToService(params); 672 return instance && instance->ConnectToService(params);
681 } 673 }
682 674
683 ServiceManager::Instance* ServiceManager::CreateInstance( 675 ServiceManager::Instance* ServiceManager::CreateInstance(
684 const Identity& source, 676 const Identity& source,
685 const Identity& target, 677 const Identity& target,
686 const CapabilitySpec& spec) { 678 const CapabilitySpec& spec) {
687 CHECK(target.user_id() != mojom::kInheritUserID); 679 CHECK(target.user_id() != mojom::kInheritUserID);
688 Instance* instance = new Instance(this, target, spec); 680
689 DCHECK(identity_to_instance_.find(target) == 681 std::unique_ptr<Instance> instance(new Instance(this, target, spec));
690 identity_to_instance_.end()); 682 Instance* raw_instance = instance.get();
683
691 Instance* source_instance = GetExistingInstance(source); 684 Instance* source_instance = GetExistingInstance(source);
692 if (source_instance) 685 if (source_instance)
693 source_instance->AddChild(instance); 686 source_instance->AddChild(std::move(instance));
694 identity_to_instance_[target] = instance; 687 else
695 mojom::ServiceInfoPtr info = instance->CreateServiceInfo(); 688 root_instances_.insert(std::make_pair(raw_instance, std::move(instance)));
689
690 // NOTE: |instance| has been passed elsewhere. Use |raw_instance| from this
691 // point forward. It's safe for the extent of this method.
692
693 auto result =
694 identity_to_instance_.insert(std::make_pair(target, raw_instance));
695 DCHECK(result.second);
696
697 mojom::ServiceInfoPtr info = raw_instance->CreateServiceInfo();
696 listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) { 698 listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) {
697 listener->OnServiceCreated(info.Clone()); 699 listener->OnServiceCreated(info.Clone());
698 }); 700 });
699 return instance; 701
702 return raw_instance;
700 } 703 }
701 704
702 void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) { 705 void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) {
703 // TODO(beng): filter instances provided by those visible to this service. 706 // TODO(beng): filter instances provided by those visible to this service.
704 std::vector<mojom::ServiceInfoPtr> instances; 707 std::vector<mojom::ServiceInfoPtr> instances;
705 instances.reserve(identity_to_instance_.size()); 708 instances.reserve(identity_to_instance_.size());
706 for (auto& instance : identity_to_instance_) 709 for (auto& instance : identity_to_instance_)
707 instances.push_back(instance.second->CreateServiceInfo()); 710 instances.push_back(instance.second->CreateServiceInfo());
708 listener->OnInit(std::move(instances)); 711 listener->OnInit(std::move(instances));
709 712
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 // Now that the instance has a Service, we can connect to it. 828 // Now that the instance has a Service, we can connect to it.
826 bool connected = instance->ConnectToService(&params); 829 bool connected = instance->ConnectToService(&params);
827 DCHECK(connected); 830 DCHECK(connected);
828 } 831 }
829 832
830 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { 833 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() {
831 return weak_ptr_factory_.GetWeakPtr(); 834 return weak_ptr_factory_.GetWeakPtr();
832 } 835 }
833 836
834 } // namespace shell 837 } // namespace shell
OLDNEW
« no previous file with comments | « services/shell/service_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698