You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
6.2 KiB

From c2e55024c6a03dcb099270718e70139542d8b0e4 Mon Sep 17 00:00:00 2001
From: Bing Xue <bingxue@google.com>
Date: Thu, 1 Aug 2019 15:47:10 -0700
Subject: [PATCH] Connect to NameOwnerChanged signal when setting callback
In ObjectManager, when ConnectToNameOwnerChangedSignal is called the first time,
we could have already missed the NameOwnerChanged signal if we get a value from
UpdateNameOwnerAndBlock. This means NameOwnerChanged callbacks will
never be called until that service restarts. In ObjectManager we run
into this problem:
1. ObjectManager::SetupMatchRuleAndFilter is called, calling
bus_->GetServiceOwnerAndBlock shows empty service name owner.
2. ObjectManager::OnSetupManagerRuleAndFilterComplete callback will call
object_proxy_->ConnectToSignal, which in turn calls
ConnectToNameOwnerChangedSignal the first time. At this point,
UpdateNameOwnerAndBlock calling bus_->GetServiceOwnerAndBlock returns the
current name owner of the service, this means the NameOwnerChanged signal
is already sent on system bus.
3. As a result, ObjectManager::NameOwnerChanged is never called while
the service is already online. This in turn causes GetManagedObject to
never be called, and the object manager interface never added.
See detailed sample logs in b/138416411.
This CL adds the following:
1. Make SetNameOwnerChangedCallback run
ConnectToNameOwnerChangedSignal when called. Since ObjectManager calls
SetNameOwnerChangedCallback before posting SetupMatchRuleAndFilter (in which
ObjectManager attempts to get the service name owner through a blocking call),
this removes the time gap described above that causes lost signal.
2. Make dbus thread the only writer to |service_name_owner_|, given that
connecting to the NameOwnerChanged signal right away in ObjectManager
ctor causes potential data race in writing to |service_name_owner_| in
both NameOwnerChanged (on origin thread) and SetupMatchRuleAndFilter (on
dbus thread).
BUG=b:138416411
TEST=Manually on device.
Change-Id: Ie95a5b7b303637acadebda151cc478e52b6a1af5
---
dbus/object_manager.cc | 20 +++++++++++++++++---
dbus/object_manager.h | 5 +++++
dbus/object_proxy.cc | 13 +++++++++++++
dbus/object_proxy.h | 3 +++
4 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/dbus/object_manager.cc b/dbus/object_manager.cc
index 05d4b2ddeabd..44f120864310 100644
--- a/dbus/object_manager.cc
+++ b/dbus/object_manager.cc
@@ -187,8 +187,12 @@ bool ObjectManager::SetupMatchRuleAndFilter() {
if (!bus_->Connect() || !bus_->SetUpAsyncOperations())
return false;
- service_name_owner_ =
- bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
+ // Try to get |service_name_owner_| from dbus if we haven't received any
+ // NameOwnerChanged signals.
+ if (service_name_owner_.empty()) {
+ service_name_owner_ =
+ bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
+ }
const std::string match_rule =
base::StringPrintf(
@@ -224,6 +228,7 @@ void ObjectManager::OnSetupMatchRuleAndFilterComplete(bool success) {
DCHECK(bus_);
DCHECK(object_proxy_);
DCHECK(setup_success_);
+ bus_->AssertOnOriginThread();
// |object_proxy_| is no longer valid if the Bus was shut down before this
// call. Don't initiate any other action from the origin thread.
@@ -505,9 +510,18 @@ void ObjectManager::RemoveInterface(const ObjectPath& object_path,
}
}
+void ObjectManager::UpdateServiceNameOwner(const std::string& new_owner) {
+ bus_->AssertOnDBusThread();
+ service_name_owner_ = new_owner;
+}
+
void ObjectManager::NameOwnerChanged(const std::string& old_owner,
const std::string& new_owner) {
- service_name_owner_ = new_owner;
+ bus_->AssertOnOriginThread();
+
+ bus_->GetDBusTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ObjectManager::UpdateServiceNameOwner, this, new_owner));
if (!old_owner.empty()) {
ObjectMap::iterator iter = object_map_.begin();
diff --git a/dbus/object_manager.h b/dbus/object_manager.h
index 05388de8e6eb..4b5fb790412d 100644
--- a/dbus/object_manager.h
+++ b/dbus/object_manager.h
@@ -317,6 +317,11 @@ class CHROME_DBUS_EXPORT ObjectManager final
void NameOwnerChanged(const std::string& old_owner,
const std::string& new_owner);
+ // Write |new_owner| to |service_name_owner_|. This method makes sure write
+ // happens on the DBus thread, which is the sole writer to
+ // |service_name_owner_|.
+ void UpdateServiceNameOwner(const std::string& new_owner);
+
Bus* bus_;
std::string service_name_;
std::string service_name_owner_;
diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc
index 7adf8f179471..de5785e98307 100644
--- a/dbus/object_proxy.cc
+++ b/dbus/object_proxy.cc
@@ -274,6 +274,10 @@ void ObjectProxy::SetNameOwnerChangedCallback(
bus_->AssertOnOriginThread();
name_owner_changed_callback_ = callback;
+
+ bus_->GetDBusTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ObjectProxy::TryConnectToNameOwnerChangedSignal, this));
}
void ObjectProxy::WaitForServiceToBeAvailable(
@@ -458,6 +462,15 @@ bool ObjectProxy::ConnectToNameOwnerChangedSignal() {
return success;
}
+void ObjectProxy::TryConnectToNameOwnerChangedSignal() {
+ bus_->AssertOnDBusThread();
+
+ bool success = ConnectToNameOwnerChangedSignal();
+ LOG_IF(WARNING, !success)
+ << "Failed to connect to NameOwnerChanged signal for object: "
+ << object_path_.value();
+}
+
bool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name,
const std::string& signal_name,
SignalCallback signal_callback) {
diff --git a/dbus/object_proxy.h b/dbus/object_proxy.h
index 22e44f1d64c0..b1bf622a12cb 100644
--- a/dbus/object_proxy.h
+++ b/dbus/object_proxy.h
@@ -267,6 +267,9 @@ class CHROME_DBUS_EXPORT ObjectProxy
// Connects to NameOwnerChanged signal.
bool ConnectToNameOwnerChangedSignal();
+ // Tries to connect to NameOwnerChanged signal, ignores any error.
+ void TryConnectToNameOwnerChangedSignal();
+
// Helper function for ConnectToSignal().
bool ConnectToSignalInternal(const std::string& interface_name,
const std::string& signal_name,
--
2.22.0.770.g0f2c4a37fd-goog