diff options
author | hashimoto <hashimoto@chromium.org> | 2015-03-30 00:01:39 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-30 07:02:21 +0000 |
commit | 41ece522bbb0cd5679e204acc8d980c6adf9ff67 (patch) | |
tree | 96c7027d02d6e92fea8f30df6f193a1243b235c1 /dbus | |
parent | 9aa653d4ac52f2c89bfa5164a5eddd8164bb9987 (diff) | |
download | chromium_src-41ece522bbb0cd5679e204acc8d980c6adf9ff67.zip chromium_src-41ece522bbb0cd5679e204acc8d980c6adf9ff67.tar.gz chromium_src-41ece522bbb0cd5679e204acc8d980c6adf9ff67.tar.bz2 |
dbus: Cancel pending calls when destroying ObjectProxy
After this change, it is guaranteed that no callback is called for method calls after
RemoveObjectProxy() is called.
BUG=471175
TEST=dbus_unittests
Review URL: https://codereview.chromium.org/1040683002
Cr-Commit-Position: refs/heads/master@{#322747}
Diffstat (limited to 'dbus')
-rw-r--r-- | dbus/end_to_end_async_unittest.cc | 27 | ||||
-rw-r--r-- | dbus/object_proxy.cc | 20 | ||||
-rw-r--r-- | dbus/object_proxy.h | 2 |
3 files changed, 44 insertions, 5 deletions
diff --git a/dbus/end_to_end_async_unittest.cc b/dbus/end_to_end_async_unittest.cc index 8846830..10516b9 100644 --- a/dbus/end_to_end_async_unittest.cc +++ b/dbus/end_to_end_async_unittest.cc @@ -418,6 +418,33 @@ TEST_F(EndToEndAsyncTest, TimeoutWithErrorCallback) { ASSERT_EQ(DBUS_ERROR_NO_REPLY, error_names_[0]); } +TEST_F(EndToEndAsyncTest, CancelPendingCalls) { + const char* kHello = "hello"; + + // Create the method call. + MethodCall method_call("org.chromium.TestInterface", "Echo"); + MessageWriter writer(&method_call); + writer.AppendString(kHello); + + // Call the method. + const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT; + CallMethod(&method_call, timeout_ms); + + // Remove the object proxy before receiving the result. + // This results in cancelling the pending method call. + bus_->RemoveObjectProxy("org.chromium.TestService", + ObjectPath("/org/chromium/TestObject"), + base::Bind(&base::DoNothing)); + + // We shouldn't receive any responses. Wait for a while just to make sure. + run_loop_.reset(new base::RunLoop); + message_loop_.PostDelayedTask(FROM_HERE, + run_loop_->QuitClosure(), + TestTimeouts::tiny_timeout()); + run_loop_->Run(); + EXPECT_TRUE(response_strings_.empty()); +} + // Tests calling a method that sends its reply asynchronously. TEST_F(EndToEndAsyncTest, AsyncEcho) { const char* kHello = "hello"; diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc index 974b24c..441dc75 100644 --- a/dbus/object_proxy.cc +++ b/dbus/object_proxy.cc @@ -60,6 +60,7 @@ ObjectProxy::ObjectProxy(Bus* bus, } ObjectProxy::~ObjectProxy() { + DCHECK(pending_calls_.empty()); } // Originally we tried to make |method_call| a const reference, but we @@ -207,16 +208,21 @@ void ObjectProxy::Detach() { if (bus_->is_connected()) bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this); - for (std::set<std::string>::iterator iter = match_rules_.begin(); - iter != match_rules_.end(); ++iter) { + for (const auto& match_rule : match_rules_) { ScopedDBusError error; - bus_->RemoveMatch(*iter, error.get()); + bus_->RemoveMatch(match_rule, error.get()); if (error.is_set()) { // There is nothing we can do to recover, so just print the error. - LOG(ERROR) << "Failed to remove match rule: " << *iter; + LOG(ERROR) << "Failed to remove match rule: " << match_rule; } } match_rules_.clear(); + + for (auto* pending_call : pending_calls_) { + dbus_pending_call_cancel(pending_call); + dbus_pending_call_unref(pending_call); + } + pending_calls_.clear(); } // static @@ -277,7 +283,7 @@ void ObjectProxy::StartAsyncMethodCall(int timeout_ms, data, &DeleteVoidPointer<OnPendingCallIsCompleteData>); CHECK(success) << "Unable to allocate memory"; - dbus_pending_call_unref(pending_call); + pending_calls_.insert(pending_call); // It's now safe to unref the request message. dbus_message_unref(request_message); @@ -297,6 +303,10 @@ void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call, start_time, response_message); bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task); + + // Remove the pending call from the set. + pending_calls_.erase(pending_call); + dbus_pending_call_unref(pending_call); } void ObjectProxy::RunResponseCallback(ResponseCallback response_callback, diff --git a/dbus/object_proxy.h b/dbus/object_proxy.h index 2c9ef51..c0211b1 100644 --- a/dbus/object_proxy.h +++ b/dbus/object_proxy.h @@ -316,6 +316,8 @@ class CHROME_DBUS_EXPORT ObjectProxy // Known name owner of the well-known bus name represented by |service_name_|. std::string service_name_owner_; + std::set<DBusPendingCall*> pending_calls_; + DISALLOW_COPY_AND_ASSIGN(ObjectProxy); }; |