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

Unified Diff: chrome/browser/sync/weak_handle.cc

Issue 7572010: [Sync] Avoid leaking in WeakHandle even when the owner thread is gone (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments Created 9 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/sync/weak_handle.h ('k') | chrome/browser/sync/weak_handle_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/sync/weak_handle.cc
diff --git a/chrome/browser/sync/weak_handle.cc b/chrome/browser/sync/weak_handle.cc
index 34eaab89f6cfdf8a9c4bb97c79ef174fedb64e52..1c78307f9fab45f584cbe1264932c4cca8a99d2c 100644
--- a/chrome/browser/sync/weak_handle.cc
+++ b/chrome/browser/sync/weak_handle.cc
@@ -4,24 +4,100 @@
#include "chrome/browser/sync/weak_handle.h"
+#include <sstream>
+
+#include "base/message_loop_proxy.h"
+#include "base/tracked.h"
+
namespace browser_sync {
namespace internal {
WeakHandleCoreBase::WeakHandleCoreBase()
- : message_loop_proxy_(
- base::MessageLoopProxy::CreateForCurrentThread()) {}
-
-WeakHandleCoreBase::~WeakHandleCoreBase() {}
+ : owner_loop_(MessageLoop::current()),
+ owner_loop_proxy_(base::MessageLoopProxy::CreateForCurrentThread()),
+ destroyed_on_owner_thread_(false) {
+ owner_loop_->AddDestructionObserver(this);
+}
bool WeakHandleCoreBase::IsOnOwnerThread() const {
- return message_loop_proxy_->BelongsToCurrentThread();
+ // We can't use |owner_loop_proxy_->BelongsToCurrentThread()| as
+ // it may not work from within a MessageLoop::DestructionObserver
+ // callback.
+ return MessageLoop::current() == owner_loop_;
+}
+
+void WeakHandleCoreBase::WillDestroyCurrentMessageLoop() {
+ CHECK(IsOnOwnerThread());
+ CHECK(!destroyed_on_owner_thread_);
+ // NOTE: This function dispatches to
+ // WeakHandle<T>::CleanupOnOwnerThread() (i.e., not just
+ // WeakHandleCoreBase::CleanupOnOwnerThread() is run).
+ CleanupOnOwnerThread();
+ CHECK(destroyed_on_owner_thread_);
+}
+
+WeakHandleCoreBase::~WeakHandleCoreBase() {
+ // It is safe to read |destroyed_on_owner_thread_| here even if
+ // we're not on the owner thread (see comments on
+ // base::AtomicRefCountDecN()).
+ CHECK(destroyed_on_owner_thread_);
+}
+
+void WeakHandleCoreBase::CleanupOnOwnerThread() {
+ CHECK(IsOnOwnerThread());
+ CHECK(!destroyed_on_owner_thread_);
+ owner_loop_->RemoveDestructionObserver(this);
+ destroyed_on_owner_thread_ = true;
}
-void WeakHandleCoreBase::PostOnOwnerThread(
+namespace {
+
+// TODO(akalin): Merge with similar function in
+// js_transaction_observer.cc.
+std::string GetLocationString(const tracked_objects::Location& location) {
+ std::ostringstream oss;
+ oss << location.function_name() << "@"
+ << location.file_name() << ":" << location.line_number();
+ return oss.str();
+}
+
+} // namespace
+
+void WeakHandleCoreBase::PostToOwnerThread(
const tracked_objects::Location& from_here,
const base::Closure& fn) const {
- ignore_result(message_loop_proxy_->PostTask(from_here, fn));
+ if (!owner_loop_proxy_->PostTask(from_here, fn)) {
+ VLOG(1) << "Could not post task from " << GetLocationString(from_here);
+ }
+}
+
+void WeakHandleCoreBase::Destroy() {
+ if (IsOnOwnerThread()) {
+ CHECK(!destroyed_on_owner_thread_);
+ CleanupAndDestroyOnOwnerThread();
+ } else if (!owner_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&WeakHandleCoreBase::CleanupAndDestroyOnOwnerThread,
+ base::Unretained(this)))) {
+ // If the post fails, that means that the owner loop is gone and
+ // therefore CleanupOnOwnerThread() should have already been
+ // called via WillDestroyCurrentMessageLoop(). Therefore, the
+ // only thing left is to self-destruct.
+ delete this;
+ }
+}
+
+void WeakHandleCoreBase::CleanupAndDestroyOnOwnerThread() {
+ CHECK(IsOnOwnerThread());
+ CHECK(!destroyed_on_owner_thread_);
+ CleanupOnOwnerThread();
+ CHECK(destroyed_on_owner_thread_);
+ delete this;
+}
+
+void WeakHandleCoreBaseTraits::Destruct(const WeakHandleCoreBase* core_base) {
+ const_cast<WeakHandleCoreBase*>(core_base)->Destroy();
}
} // namespace internal
« no previous file with comments | « chrome/browser/sync/weak_handle.h ('k') | chrome/browser/sync/weak_handle_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698