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

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

Issue 2572803002: [ServiceManager] Eliminate parent-child relationship between services (Closed)
Patch Set: More general fix for ConnectTest shutdown deadlock Created 4 years 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 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/service_manager/service_manager.h" 5 #include "services/service_manager/service_manager.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 control_binding_(this), 94 control_binding_(this),
95 state_(State::IDLE), 95 state_(State::IDLE),
96 weak_factory_(this) { 96 weak_factory_(this) {
97 if (identity_.name() == service_manager::mojom::kServiceName || 97 if (identity_.name() == service_manager::mojom::kServiceName ||
98 identity_.name() == catalog::mojom::kServiceName) { 98 identity_.name() == catalog::mojom::kServiceName) {
99 pid_ = base::Process::Current().Pid(); 99 pid_ = base::Process::Current().Pid();
100 } 100 }
101 DCHECK_NE(mojom::kInvalidInstanceID, id_); 101 DCHECK_NE(mojom::kInvalidInstanceID, id_);
102 } 102 }
103 103
104 ~Instance() override { 104 void Stop() {
105 // Shutdown all bindings before we close the runner. This way the process 105 // Shutdown all bindings. This way the process should see the pipes closed
106 // should see the pipes closed and exit, as well as waking up any potential 106 // and exit, as well as waking up any potential
107 // sync/WaitForIncomingResponse(). 107 // sync/WaitForIncomingResponse().
108 service_.reset(); 108 service_.reset();
109 if (pid_receiver_binding_.is_bound()) 109 if (pid_receiver_binding_.is_bound())
110 pid_receiver_binding_.Close(); 110 pid_receiver_binding_.Close();
111 connectors_.CloseAllBindings(); 111 connectors_.CloseAllBindings();
112 service_manager_bindings_.CloseAllBindings(); 112 service_manager_bindings_.CloseAllBindings();
113 service_manager_->OnInstanceUnreachable(this); 113 service_manager_->OnInstanceUnreachable(this);
114 114
115 if (state_ == State::STARTING) { 115 if (state_ == State::STARTING) {
116 service_manager_->NotifyServiceFailedToStart(identity_); 116 service_manager_->NotifyServiceFailedToStart(identity_);
117 } else { 117 } else {
118 // Notify the ServiceManager that this Instance is really going away. 118 // Notify the ServiceManager that this Instance is really going away.
119 service_manager_->OnInstanceStopped(identity_); 119 service_manager_->OnInstanceStopped(identity_);
120 } 120 }
121 }
122
123 ~Instance() override {
124 Stop();
121 125
122 // Release |runner_| so that if we are called back to OnRunnerCompleted() 126 // Release |runner_| so that if we are called back to OnRunnerCompleted()
123 // we know we're in the destructor. 127 // we know we're in the destructor.
124 std::unique_ptr<NativeRunner> runner = std::move(runner_); 128 std::unique_ptr<NativeRunner> runner = std::move(runner_);
125 runner.reset(); 129 runner.reset();
126 } 130 }
127 131
128 Instance* parent() const { return parent_; }
129
130 void AddChild(std::unique_ptr<Instance> child) {
131 child->parent_ = this;
132 children_.insert(std::make_pair(child.get(), std::move(child)));
133 }
134
135 void RemoveChild(Instance* child) {
136 auto it = children_.find(child);
137 DCHECK(it != children_.end());
138
139 // Deletes |child|.
140 children_.erase(it);
141 }
142
143 bool ConnectToService(std::unique_ptr<ConnectParams>* connect_params) { 132 bool ConnectToService(std::unique_ptr<ConnectParams>* connect_params) {
144 if (!service_.is_bound()) 133 if (!service_.is_bound())
145 return false; 134 return false;
146 135
147 std::unique_ptr<ConnectParams> params(std::move(*connect_params)); 136 std::unique_ptr<ConnectParams> params(std::move(*connect_params));
148 if (!params->connect_callback().is_null()) { 137 if (!params->connect_callback().is_null()) {
149 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED, 138 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED,
150 identity_.user_id()); 139 identity_.user_id());
151 } 140 }
152 141
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 const InterfaceProviderSpecMap interface_provider_specs_; 455 const InterfaceProviderSpecMap interface_provider_specs_;
467 const InterfaceProviderSpec empty_spec_; 456 const InterfaceProviderSpec empty_spec_;
468 const bool allow_any_application_; 457 const bool allow_any_application_;
469 std::unique_ptr<NativeRunner> runner_; 458 std::unique_ptr<NativeRunner> runner_;
470 mojom::ServicePtr service_; 459 mojom::ServicePtr service_;
471 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; 460 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_;
472 mojo::BindingSet<mojom::Connector> connectors_; 461 mojo::BindingSet<mojom::Connector> connectors_;
473 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; 462 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_;
474 mojo::AssociatedBinding<mojom::ServiceControl> control_binding_; 463 mojo::AssociatedBinding<mojom::ServiceControl> control_binding_;
475 base::ProcessId pid_ = base::kNullProcessId; 464 base::ProcessId pid_ = base::kNullProcessId;
476 Instance* parent_ = nullptr;
477 InstanceMap children_;
478 State state_; 465 State state_;
479 466
480 // The number of outstanding OnConnect requests which are in flight. 467 // The number of outstanding OnConnect requests which are in flight.
481 int pending_service_connections_ = 0; 468 int pending_service_connections_ = 0;
482 469
483 base::WeakPtrFactory<Instance> weak_factory_; 470 base::WeakPtrFactory<Instance> weak_factory_;
484 471
485 DISALLOW_COPY_AND_ASSIGN(Instance); 472 DISALLOW_COPY_AND_ASSIGN(Instance);
486 }; 473 };
487 474
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 547
561 if (catalog) 548 if (catalog)
562 InitCatalog(std::move(catalog)); 549 InitCatalog(std::move(catalog));
563 } 550 }
564 551
565 ServiceManager::~ServiceManager() { 552 ServiceManager::~ServiceManager() {
566 // Ensure we tear down the ServiceManager instance last. This is to avoid 553 // Ensure we tear down the ServiceManager instance last. This is to avoid
567 // hitting bindings DCHECKs, since the ServiceManager or Catalog may at any 554 // hitting bindings DCHECKs, since the ServiceManager or Catalog may at any
568 // given time own in-flight responders for Instances' Connector requests. 555 // given time own in-flight responders for Instances' Connector requests.
569 std::unique_ptr<Instance> service_manager_instance; 556 std::unique_ptr<Instance> service_manager_instance;
570 auto iter = root_instances_.find(service_manager_instance_); 557 auto iter = instances_.find(service_manager_instance_);
571 DCHECK(iter != root_instances_.end()); 558 DCHECK(iter != instances_.end());
572 service_manager_instance = std::move(iter->second); 559 service_manager_instance = std::move(iter->second);
573 560
574 root_instances_.clear(); 561 // Stop all of the instances before destroying any of them. This ensures that
562 // all Services will receive connection errors and avoids possible deadlock in
563 // the case where one Instance's destructor blocks waiting for its Runner to
564 // quit, while that Runner's corresponding Service blocks its shutdown on a
565 // distinct Service receiving a connection error.
566 for (const auto& instance : instances_)
567 instance.first->Stop();
568 service_manager_instance->Stop();
569
570 instances_.clear();
575 } 571 }
576 572
577 void ServiceManager::SetServiceOverrides( 573 void ServiceManager::SetServiceOverrides(
578 std::unique_ptr<ServiceOverrides> overrides) { 574 std::unique_ptr<ServiceOverrides> overrides) {
579 service_overrides_ = std::move(overrides); 575 service_overrides_ = std::move(overrides);
580 } 576 }
581 577
582 void ServiceManager::SetInstanceQuitCallback( 578 void ServiceManager::SetInstanceQuitCallback(
583 base::Callback<void(const Identity&)> callback) { 579 base::Callback<void(const Identity&)> callback) {
584 instance_quit_callback_ = callback; 580 instance_quit_callback_ = callback;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 identity_to_resolver_[identity] = std::move(resolver_ptr); 631 identity_to_resolver_[identity] = std::move(resolver_ptr);
636 return resolver; 632 return resolver;
637 } 633 }
638 634
639 void ServiceManager::OnInstanceError(Instance* instance) { 635 void ServiceManager::OnInstanceError(Instance* instance) {
640 // We never clean up the ServiceManager's own instance. 636 // We never clean up the ServiceManager's own instance.
641 if (instance == service_manager_instance_) 637 if (instance == service_manager_instance_)
642 return; 638 return;
643 639
644 EraseInstanceIdentity(instance); 640 EraseInstanceIdentity(instance);
645 if (instance->parent()) { 641 auto it = instances_.find(instance);
646 // Deletes |instance|. 642 DCHECK(it != instances_.end());
647 instance->parent()->RemoveChild(instance);
648 } else {
649 auto it = root_instances_.find(instance);
650 DCHECK(it != root_instances_.end());
651 643
652 // Deletes |instance|. 644 // Deletes |instance|.
653 root_instances_.erase(it); 645 instances_.erase(it);
654 }
655 } 646 }
656 647
657 void ServiceManager::OnInstanceUnreachable(Instance* instance) { 648 void ServiceManager::OnInstanceUnreachable(Instance* instance) {
658 // If an Instance becomes unreachable, new connection requests for this 649 // If an Instance becomes unreachable, new connection requests for this
659 // identity will elicit a new Instance instantiation. The unreachable instance 650 // identity will elicit a new Instance instantiation. The unreachable instance
660 // remains alive. 651 // remains alive.
661 EraseInstanceIdentity(instance); 652 EraseInstanceIdentity(instance);
662 } 653 }
663 654
664 void ServiceManager::OnInstanceStopped(const Identity& identity) { 655 void ServiceManager::OnInstanceStopped(const Identity& identity) {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 753
763 ServiceManager::Instance* ServiceManager::CreateInstance( 754 ServiceManager::Instance* ServiceManager::CreateInstance(
764 const Identity& source, 755 const Identity& source,
765 const Identity& target, 756 const Identity& target,
766 const InterfaceProviderSpecMap& specs) { 757 const InterfaceProviderSpecMap& specs) {
767 CHECK(target.user_id() != mojom::kInheritUserID); 758 CHECK(target.user_id() != mojom::kInheritUserID);
768 759
769 auto instance = base::MakeUnique<Instance>(this, target, specs); 760 auto instance = base::MakeUnique<Instance>(this, target, specs);
770 Instance* raw_instance = instance.get(); 761 Instance* raw_instance = instance.get();
771 762
772 Instance* source_instance = GetExistingInstance(source); 763 instances_.insert(std::make_pair(raw_instance, std::move(instance)));
773 if (source_instance)
774 source_instance->AddChild(std::move(instance));
775 else
776 root_instances_.insert(std::make_pair(raw_instance, std::move(instance)));
777 764
778 // NOTE: |instance| has been passed elsewhere. Use |raw_instance| from this 765 // NOTE: |instance| has been passed elsewhere. Use |raw_instance| from this
779 // point forward. It's safe for the extent of this method. 766 // point forward. It's safe for the extent of this method.
780 767
781 auto result = 768 auto result =
782 identity_to_instance_.insert(std::make_pair(target, raw_instance)); 769 identity_to_instance_.insert(std::make_pair(target, raw_instance));
783 DCHECK(result.second); 770 DCHECK(result.second);
784 771
785 mojom::RunningServiceInfoPtr info = raw_instance->CreateRunningServiceInfo(); 772 mojom::RunningServiceInfoPtr info = raw_instance->CreateRunningServiceInfo();
786 listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) { 773 listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 // Now that the instance has a Service, we can connect to it. 948 // Now that the instance has a Service, we can connect to it.
962 bool connected = instance->ConnectToService(&params); 949 bool connected = instance->ConnectToService(&params);
963 DCHECK(connected); 950 DCHECK(connected);
964 } 951 }
965 952
966 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { 953 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() {
967 return weak_ptr_factory_.GetWeakPtr(); 954 return weak_ptr_factory_.GetWeakPtr();
968 } 955 }
969 956
970 } // namespace service_manager 957 } // namespace service_manager
OLDNEW
« no previous file with comments | « services/service_manager/service_manager.h ('k') | services/service_manager/tests/lifecycle/lifecycle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698