summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorerg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 23:38:18 +0000
committererg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 23:38:18 +0000
commit0e3a385d57bb5f0080e930b37fb8c6f14408cafb (patch)
treeb50d9d3a38564f250866157e5157268defb7b786 /chrome
parentf90a0fb4d44ae9d3fca4adf05b76f187c09840f6 (diff)
downloadchromium_src-0e3a385d57bb5f0080e930b37fb8c6f14408cafb.zip
chromium_src-0e3a385d57bb5f0080e930b37fb8c6f14408cafb.tar.gz
chromium_src-0e3a385d57bb5f0080e930b37fb8c6f14408cafb.tar.bz2
Profiles: When built in debug mode, NOTREACHED() after a Profile is shutdown if it is accessed.
BUG=77155 TEST=These extra NOTREACHED() don't trigger. Review URL: http://codereview.chromium.org/7074019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86929 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/profiles/profile.cc4
-rw-r--r--chrome/browser/profiles/profile_dependency_manager.cc20
-rw-r--r--chrome/browser/profiles/profile_dependency_manager.h24
-rw-r--r--chrome/browser/profiles/profile_impl.cc5
-rw-r--r--chrome/browser/profiles/profile_keyed_service_factory.cc8
-rw-r--r--chrome/test/testing_profile.cc4
6 files changed, 65 insertions, 0 deletions
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index 85bbef2..4f882cb 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -200,6 +200,10 @@ class OffTheRecordProfileImpl : public Profile,
prefs_(real_profile->GetOffTheRecordPrefs()),
ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)),
start_time_(Time::Now()) {
+#ifndef NDEBUG
+ ProfileDependencyManager::GetInstance()->ProfileNowExists(this);
+#endif
+
extension_process_manager_.reset(ExtensionProcessManager::Create(this));
BrowserList::AddObserver(this);
diff --git a/chrome/browser/profiles/profile_dependency_manager.cc b/chrome/browser/profiles/profile_dependency_manager.cc
index 590a5b3..e6479ad 100644
--- a/chrome/browser/profiles/profile_dependency_manager.cc
+++ b/chrome/browser/profiles/profile_dependency_manager.cc
@@ -55,12 +55,32 @@ void ProfileDependencyManager::DestroyProfileServices(Profile* profile) {
(*it)->ProfileShutdown(profile);
}
+#ifndef NDEBUG
+ // The profile is now dead to the rest of the program.
+ dead_profile_pointers_.insert(profile);
+#endif
+
for (std::vector<ProfileKeyedServiceFactory*>::const_iterator it =
destruction_order_.begin(); it != destruction_order_.end(); ++it) {
(*it)->ProfileDestroyed(profile);
}
}
+#ifndef NDEBUG
+void ProfileDependencyManager::ProfileNowExists(Profile* profile) {
+ dead_profile_pointers_.erase(profile);
+}
+
+void ProfileDependencyManager::AssertProfileWasntDestroyed(Profile* profile) {
+ if (dead_profile_pointers_.find(profile) != dead_profile_pointers_.end()) {
+ NOTREACHED() << "Attempted to access a Profile that was ShutDown(). This "
+ << "is most likely a heap smasher in progress. After "
+ << "ProfileKeyedService::Shutdown() completes, your service "
+ << "MUST NOT refer to depended Profile services again.";
+ }
+}
+#endif
+
// static
ProfileDependencyManager* ProfileDependencyManager::GetInstance() {
return Singleton<ProfileDependencyManager>::get();
diff --git a/chrome/browser/profiles/profile_dependency_manager.h b/chrome/browser/profiles/profile_dependency_manager.h
index 09fd381..b477bb7 100644
--- a/chrome/browser/profiles/profile_dependency_manager.h
+++ b/chrome/browser/profiles/profile_dependency_manager.h
@@ -10,6 +10,10 @@
#include "base/memory/singleton.h"
+#ifndef NDEBUG
+#include <set>
+#endif
+
class Profile;
class ProfileKeyedServiceFactory;
@@ -39,6 +43,18 @@ class ProfileDependencyManager {
// replaced in many tests.
void DestroyProfileServices(Profile* profile);
+#ifndef NDEBUG
+ // Unmark |profile| as dead. This exists because of unit tests, which will
+ // often have similar stack structures. 0xWhatever might be created, go out
+ // of scope, and then a new Profile object might be created at 0xWhatever.
+ void ProfileNowExists(Profile* profile);
+
+ // Debugging assertion called as part of GetServiceForProfile in debug
+ // mode. This will NOTREACHED() whenever the user is trying to access a stale
+ // Profile*.
+ void AssertProfileWasntDestroyed(Profile* profile);
+#endif
+
static ProfileDependencyManager* GetInstance();
private:
@@ -60,6 +76,14 @@ class ProfileDependencyManager {
EdgeMap edges_;
std::vector<ProfileKeyedServiceFactory*> destruction_order_;
+
+#ifndef NDEBUG
+ // A list of profile objects that have gone through the Shutdown()
+ // phase. These pointers are most likely invalid, but we keep track of their
+ // locations in memory so we can nicely assert if we're asked to do anything
+ // with them.
+ std::set<Profile*> dead_profile_pointers_;
+#endif
};
#endif // CHROME_BROWSER_PROFILES_PROFILE_DEPENDENCY_MANAGER_H_
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 5d8b6ad..c36d91d 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -294,6 +294,11 @@ ProfileImpl::ProfileImpl(const FilePath& path,
delegate_(delegate) {
DCHECK(!path.empty()) << "Using an empty path will attempt to write " <<
"profile files to the root directory!";
+
+#ifndef NDEBUG
+ ProfileDependencyManager::GetInstance()->ProfileNowExists(this);
+#endif
+
create_session_service_timer_.Start(
TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this,
&ProfileImpl::EnsureSessionServiceCreated);
diff --git a/chrome/browser/profiles/profile_keyed_service_factory.cc b/chrome/browser/profiles/profile_keyed_service_factory.cc
index 8515714..2a1af3d 100644
--- a/chrome/browser/profiles/profile_keyed_service_factory.cc
+++ b/chrome/browser/profiles/profile_keyed_service_factory.cc
@@ -25,10 +25,18 @@ ProfileKeyedServiceFactory::~ProfileKeyedServiceFactory() {
ProfileKeyedService* ProfileKeyedServiceFactory::GetServiceForProfile(
Profile* profile,
bool create) {
+#ifndef NDEBUG
+ dependency_manager_->AssertProfileWasntDestroyed(profile);
+#endif
+
// Possibly handle Incognito mode.
if (profile->IsOffTheRecord()) {
if (ServiceRedirectedInIncognito()) {
profile = profile->GetOriginalProfile();
+
+#ifndef NDEBUG
+ dependency_manager_->AssertProfileWasntDestroyed(profile);
+#endif
} else if (ServiceHasOwnInstanceInIncognito()) {
// No-op; the pointers are already set correctly.
} else {
diff --git a/chrome/test/testing_profile.cc b/chrome/test/testing_profile.cc
index 0ae4404..3604f9d 100644
--- a/chrome/test/testing_profile.cc
+++ b/chrome/test/testing_profile.cc
@@ -128,6 +128,10 @@ TestingProfile::TestingProfile()
incognito_(false),
last_session_exited_cleanly_(true),
profile_dependency_manager_(ProfileDependencyManager::GetInstance()) {
+#ifndef NDEBUG
+ profile_dependency_manager_->ProfileNowExists(this);
+#endif
+
if (!temp_dir_.CreateUniqueTempDir()) {
LOG(ERROR) << "Failed to create unique temporary directory.";